Android Architecture Components: using ViewModel for RecyclerView items

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.


First of all correct implementation of ViewModel should be by extending android.arch.lifecycle.ViewModel. The examples that extending BaseObservable which makes ViewModel class a data class but it should be presentation class since it's replacing the presenter of MVP pattern.

Another thing is ViewModelProviders.of(context).get(Class.class) returns the same ViewModel for every call and it lets you to share same data between views.

Also, ViewModel class should not, or contain minimum classes from Android environment and should not keep any references to view classes since it may outlive the views.

In your second example you probably getting same ViewModel from Activity/Fragment using

public void setViewModel(GalleryItemViewModel viewModel){
            this.viewModel = viewModel;
            binding.setViewModel(viewModel);
}

Can you share layout file and how you implement this with ViewModel class?

Link for sample in accepted answer is not a correct example for MVVM and data binding.

ViewModel class from the link set as you second example:

public class CommentHeaderViewModel extends BaseObservable {

    private Context context;
    private Post post;

    public CommentHeaderViewModel(Context context, Post post) {
        this.context = context;
        this.post = post;
    }

    public String getCommentText() {
        return Html.fromHtml(post.text.trim()).toString();
    }

    public String getCommentAuthor() {
        return context.getResources().getString(R.string.text_comment_author, post.by);
    }

    public String getCommentDate() {
        return new PrettyTime().format(new Date(post.time * 1000));
    }

}

This is a data class, not an ViewModel class as architecture components page states, it also imports view classes which is bad for unit testing.

It's data binding + RecyclerView tutorial, correct naming should not be ..ViewModel for this class. Check out this tutorial for data class and binding it with RecyclerView.