Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

update RecyclerView with Android LiveData

There are many examples how to push new list to adapter on LiveData change.

I'm trying to update one row (e.g number of comments for post) in the huge list. It would be stupid to reset whole list to change only one field.

I am able to add observer onBindViewHolder, but I can't understand when should I remove observer

@Override
public void onBindViewHolder(ViewHolder vh, int position) {
    Post post = getPost(position);
    vh.itemView.setTag(post);
    post.getLiveName().observeForever(vh.nameObserver);
    ... 
}
like image 398
Andrew Matiuk Avatar asked Jun 11 '17 22:06

Andrew Matiuk


2 Answers

Like @Lyla said, you should observe the whole list as LiveData in Fragment or Activity, when receive changes, you should set the whole list to the adapter by DiffUtil.

Fake code:

PostViewModel {
    LiveData<List<Post>> posts;  // posts comes from DAO or Webservice
}

MyFragment extends LifecycleFragment {
    PostAdapter postAdapter;

    ...

    void onActivityCreated() {
        ...
        postViewModel.posts.observer(this, (postList) -> {
            postAdapter.setPosts(postList);
        }
    }       
}

PostAdapter {
    void setPosts(List<Post> postList) {
        DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {...}
        ...
    }
}
like image 111
Spark.Bao Avatar answered Oct 14 '22 01:10

Spark.Bao


Using DiffUtil might help with updating one row in a huge list. You can then have LiveData wrap the list of comments instead of a single comment or attribute of a comment.

Here's an example of using DiffUtil within a RecyclerView adapter and the list LiveData observation code in the fragment.

like image 13
Lyla Avatar answered Oct 14 '22 01:10

Lyla