Home > Software engineering >  I need help regrading deleting items inside RecyclerView. Deletion works but updating RecyclerView s
I need help regrading deleting items inside RecyclerView. Deletion works but updating RecyclerView s

Time:07-07

Sometimes delete function works sometimes not. I think the problem is with the notifyItemRemove or removing items inside the array. Worked on finding the bug for 3 days but in vain. This is the adapter class

public class ChecklistItems extends AppCompatActivity {
Toolbar toolbar;
RecyclerView recyclerView;

String content;
String status;

String[] contentSplit;
String[] statusSplit;

private ChecklistAdapter checklistAdapter;
DbHelper dbHelper;
List<ChecklistHelper> checks;
int id;
ChecklistHelper checklistHelper;
StringBuilder stringBuilderContent;
StringBuilder stringBuilderStatus;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_checklist_items);

    toolbar = findViewById(R.id.tool_bar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    recyclerView = findViewById(R.id.recycler_view_child);


    id = getIntent().getIntExtra("id", 0);
    content = getIntent().getStringExtra("content");
    status = getIntent().getStringExtra("status");

    contentSplit = content.split("\n");
    statusSplit = status.split("\n");

    checklistHelper = new ChecklistHelper();
    dbHelper = new DbHelper(this);

    checks = dbHelper.getChecklists();
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    
    checklistHelper =  dbHelper.getChecklists(id);
    String status = checklistHelper.getStatus();
    String[] statusSplit = status.split("\n");
    ArrayList<String> newStatusList = new ArrayList<>(Arrays.asList(statusSplit));
    ArrayList<String> newContentList = new ArrayList<>(Arrays.asList(statusSplit));

    checklistAdapter = new ChecklistAdapter(newStatusList, newContentList);
    recyclerView.setAdapter(checklistAdapter);
}


public class ChecklistAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    ArrayList<String> newStatusList;
    ArrayList<String> newContentList;
    
    public ChecklistAdapter( ArrayList<String> newStatusList, ArrayList<String> newContentList) {
        
        this.newStatusList = newStatusList;
        this.newContentList = newContentList;
    }
    
    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        View view = layoutInflater.inflate(R.layout.checklist_layout_child, parent, false);
        return new ChecklistChildViewHolder(view);

    }
    
    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, @SuppressLint("RecyclerView") int position) {

        ChecklistChildViewHolder checklistChildViewHolder = (ChecklistChildViewHolder) holder;
        checklistChildViewHolder.checkBox.setText(contentSplit[position]);

        boolean state;
        if (statusSplit[position].equals("1")) {
            state = true;
            checklistChildViewHolder.checkBox.setText(lineThrough(checklistChildViewHolder.checkBox.getText().toString()));
        }
        else
        {
            state = false;
            checklistChildViewHolder.checkBox.setText(checklistChildViewHolder.checkBox.getText().toString());
        }
        checklistChildViewHolder.checkBox.setChecked(state);

        checklistChildViewHolder.delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                doDelete(position);
            }
        });
    }

    @Override
    public int getItemCount() {
        return newStatusList.size();

    }

    public class ChecklistChildViewHolder extends RecyclerView.ViewHolder {
        CheckBox checkBox;
        ImageView delete, edit;

        ChecklistChildViewHolder(@NonNull View itemView) {
            super(itemView);
            checkBox = itemView.findViewById(R.id.checkbox_child);
            delete = itemView.findViewById(R.id.delete_child);
            edit = itemView.findViewById(R.id.edit_child);
            delete.setVisibility(View.INVISIBLE);
            edit.setVisibility(View.INVISIBLE);
        }

        public void updateVisibility(boolean isEnableDelete){

            if (isEnableDelete) {
                delete.setVisibility(View.VISIBLE);
                edit.setVisibility(View.VISIBLE);
            }
            else {
                delete.setVisibility(View.INVISIBLE);
                edit.setVisibility(View.INVISIBLE);
            }
        }
    }

    public int doDelete(int position) {

        int idd = getIntent().getIntExtra("id", 0);
        checklistHelper =  dbHelper.getChecklists(idd);

        String status = checklistHelper.getStatus();
        String content = checklistHelper.getContent();

        String[] statusSplit = status.split("\n");
        String[] contentSplit = content.split("\n");

        newStatusList = new ArrayList<>(Arrays.asList(statusSplit));
        newContentList = new ArrayList<>(Arrays.asList(contentSplit));

        newStatusList.remove(position);
        newContentList.remove(position);
        
        stringBuilderStatus = new StringBuilder();
        stringBuilderContent = new StringBuilder();

        for(String singleStatus : newStatusList) {
            stringBuilderStatus.append(singleStatus);
            stringBuilderStatus.append("\n");
        }

        for(String singleContent: newContentList){
            stringBuilderContent.append(singleContent);
            stringBuilderContent.append("\n");
        }
        String allStatus = stringBuilderStatus.toString();
        String allContent = stringBuilderContent.toString();
        dbHelper.updateChecklist(id,allStatus , allContent, DateTime.date(), DateTime.time(), System.currentTimeMillis());

        if(allContent.length()==0) {
            dbHelper.deleteChecklist(id);
            finish();
        }
        
        notifyItemRemoved(position);
        notifyItemChanged(position);

        return newStatusList.size();
    }
}

} I have used most of the (notify) functions which update the RecyclerView but none worked properly.

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_checklist_items);

    toolbar = findViewById(R.id.tool_bar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    recyclerView = findViewById(R.id.recycler_view_child);
    
    id = getIntent().getIntExtra("id", 0);
    content = getIntent().getStringExtra("content");
    status = getIntent().getStringExtra("status");

    contentSplit = content.split("\n");
    statusSplit = status.split("\n");

    checklistHelper = new ChecklistHelper();
    dbHelper = new DbHelper(this);
    
    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    recyclerView.setAdapter(checklistAdapter);


    checklistHelper =  dbHelper.getChecklists(id);
    String status = checklistHelper.getStatus();
    String[] statusSplit = status.split("\n");
    ArrayList<String> newStatusList = new ArrayList<>(Arrays.asList(statusSplit));
    ArrayList<String> newContentList = new ArrayList<>(Arrays.asList(statusSplit));

    checklistAdapter = new ChecklistAdapter(newStatusList, newContentList);
    recyclerView.setAdapter(checklistAdapter);
}

CodePudding user response:

Your problem is notifyItemChanged(position);. When you remove an item, you are changing the position of all other items beyond it.

You want to use notifyItemRangeChanged(position, newContentList.size()); as this will take into account the shifting positions.

You use notifyItemChanged(position); if the content of the position has changed, but the position it self remains the same.

CodePudding user response:

you need to remove the lines in doDelete method:

 newStatusList = new ArrayList<>(Arrays.asList(statusSplit));
 newContentList = new ArrayList<>(Arrays.asList(contentSplit));

two lines will re-assign the new object and the underlay data may not locate in the same memory position as the old newStatusList and newContentList

And you can use Adapter.notifyDataSetChanged() instead of notifyItemXXX

  • Related