androidfirebase-realtime-databaseandroid-recyclerviewnotifydatasetchanged

Android recyclerview shows more values after data change


I am trying to edit an item in a recyclerview which shows some data from Firebase. But after editing the data set is not changed. It shows previous as well as the new updated items, until the activity is reloaded. The screenshots are given at the end.

I am editing the items via an alertdialog. Following is the code:

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.MyViewHolder> {
    ArrayList<User_Post> user_posts=null;
Context context;
public ListAdapter(@Nullable ArrayList<User_Post> posts, Context c) {
        this.user_posts=posts;      // the data set
        this.context=c;
    }

Upon item's edit button click the AlertDialog opens:

  //'post' is an instance of type User_Post containing the current data item.

dialogBuilder.setPositiveButton("Save", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
        if(isValid()) {
            post.setWorkType(txtType.getSelectedItem().toString());
            post.setWorkDescription(txtDetails.getText().toString());

            user_posts.set(position,post);
            updateDataSet(user_posts);

            saveToFirebase(post,"edit");
            Toast.makeText(context, "Post updated", Toast.LENGTH_SHORT).show();

        }
    }
}

Code for updating firebase data:

private void saveToFirebase(User_Post post, String task) {
    String id=post.getPostID();

    FirebaseDatabase database = FirebaseDatabase.getInstance();
    FirebaseStorage storage = FirebaseStorage.getInstance();
    StorageReference storageRef = storage.getReferenceFromUrl("gs://smart-worker-c73c4.appspot.com/gs:");
    DatabaseReference myRef = database.getReference("posts");

    if(task.equals("edit")) {
        myRef.child(id).setValue(post);
    }
    else {
        myRef.child(id).setValue(null);
        storageRef.child(id).delete();
    }
}

For updating data set:

private void updateDataSet(ArrayList<User_Post> posts){
    this.user_posts=posts;
    notifyDataSetChanged();
}

Screenshot before editing... enter image description here

Screenshot after editing... enter image description here


Solution

  • It shows previous as well as the new updated items, until the activity is reloaded

    So, when you reload the activity, the new data is shown on the RecyclerView, therefore the data is saved successfully into firebase, and grabbed in reloading the activity. So, the issue is not related to firebase.

    Also you decided not to have a persistent event listener to firebase, instead you updated the RecyclerView locally with:

     private void updateDataSet(ArrayList<User_Post> posts){
            this.user_posts = posts;
            notifyDataSetChanged();
    }
    

    Although I'd suggest to clear, and then rebuild the list before notifying the change:

     private void updateDataSet(ArrayList<User_Post> posts){
            this.user_posts.clear();
            this.user_posts.addAll(posts);        
            notifyDataSetChanged();
    }
    

    This is not the optimum procedure, because calling notifyDataSetChanged() is expensive; instead I'd recommend to notifyItemInserted() or notifyItemRangeChanged(); to deploy only the changes to the RecyclerView.

    For instance if you just will pass a single item:

     private void updateDataSet(User_Post post){
            this.user_posts.add(post);        
            notifyItemInserted(this.user_posts.size()-1);
    }
    

    And for a range of items:

     private void updateDataSet(ArrayList<User_Post> posts){ // Pass only those items that are changed
            int currentSize = this.user_posts.size();
            this.user_posts.addAll(posts);   
            int newSize = this.user_posts.size();     
            notifyItemInserted(currentSize, newSize - 1);
    }