Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Architecture Components: using ViewModel for RecyclerView items

I'm experimenting with the Architecture Components, and I want to build a ViewModel for each item of a RecyclerView. I'm not sure if that is formally correct or I should stick with the "old way".

I have this adapter:

public class PostAdapter extends RecyclerView.Adapter<PostAdapter.PostViewHolder> {      private List<Post> list;     public static class PostViewHolder extends RecyclerView.ViewHolder{         final ItemPostBinding binding;          public PostViewHolder(ItemPostBinding binding){             super(binding.getRoot());             this.binding = binding;         }     }      @Override     public PostViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {         ItemPostBinding binding = DataBindingUtil                 .inflate(LayoutInflater.from(parent.getContext()), R.layout.item_post,                         parent, false);           return new PostViewHolder(binding, parent.getContext());     }      @Override     public void onBindViewHolder(PostViewHolder holder, int position) {         holder.binding.setPost(list.get(position));         holder.binding.executePendingBindings();     }      @Override     public int getItemCount() {         return list == null ? 0 : list.size();     }      public void setList(List<Post> list){         this.list = list;         notifyDataSetChanged();     } } 

which works fine but it's very basic. how do I update it so each item has it's own ViewModel associated? is that even possible?

EDIT: playing with it, I've tried to put in ViewModels the following way:

public class PostAdapter extends RecyclerView.Adapter<PostAdapter.PostViewHolder> {      private List<Post> list;     public static class PostViewHolder extends RecyclerView.ViewHolder{         final ItemPostBinding binding;         private final Context context;         private GalleryItemViewModel viewModel;          public PostViewHolder(ItemPostBinding binding, Context context){             super(binding.getRoot());             this.binding = binding;             this.context = context;         }          public Context getContext(){             return context;         }          public void setViewModel(GalleryItemViewModel viewModel){             this.viewModel = viewModel;             binding.setViewModel(viewModel);         }     }      @Override     public PostViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {         ItemPostBinding binding = DataBindingUtil                 .inflate(LayoutInflater.from(parent.getContext()), R.layout.item_post,                         parent, false);           return new PostViewHolder(binding, parent.getContext());     }      @Override     public void onBindViewHolder(PostViewHolder holder, int position) {         GalleryItemViewModel vm = ViewModelProviders.of((FragmentActivity) holder.getContext()).get(GalleryItemViewModel.class);         vm.setPost(list.get(position));         holder.setViewModel(vm);     }      @Override     public int getItemCount() {         return list == null ? 0 : list.size();     }      public void setList(List<Post> list){         this.list = list;         notifyDataSetChanged();     } } 

it works but is that the correct way to do it?

like image 241
jack_the_beast Avatar asked Nov 23 '17 10:11

jack_the_beast


People also ask

What is the use of ViewHolder in RecyclerView Android?

A ViewHolder describes an item view and metadata about its place within the RecyclerView. Adapter implementations should subclass ViewHolder and add fields for caching potentially expensive findViewById results.

Which is better ListView or RecyclerView?

Simple answer: You should use RecyclerView in a situation where you want to show a lot of items, and the number of them is dynamic. ListView should only be used when the number of items is always the same and is limited to the screen size.

What is the use of onBindViewHolder in Android?

bindViewHolder. This method internally calls onBindViewHolder to update the ViewHolder contents with the item at the given position and also sets up some private fields to be used by RecyclerView.


1 Answers

Funny, but answer - This is correct way, should be accepted :) You can make some code clean-up and remove GalleryItemViewModel from PostViewHolder, because you are creating hard reference and not using it. Then dirrectly in onBindViewHolder() use it like holder.binding.setViewModel(vm);

This is a link with MVVM code example that can help you.

like image 119
Stanislav Bondar Avatar answered Oct 12 '22 17:10

Stanislav Bondar