Android体系结构组件:将ViewModel用于RecyclerView项 [英] Android Architecture Components: using ViewModel for RecyclerView items

查看:1395
本文介绍了Android体系结构组件:将ViewModel用于RecyclerView项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试架构组件",我想为RecyclerView的每个项目构建一个ViewModel.我不确定这在形式上是否正确,还是我应该坚持旧方法".

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".

我有此适配器:

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();
    }
}

可以正常工作,但这是非常基本的.如何更新它,以便每个项目都有自己的ViewModel关联?那有可能吗?

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?

使用它,我尝试通过以下方式放入ViewModels:

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?

推荐答案

首先,正确地实现ViewModel的方法是扩展android.arch.lifecycle.ViewModel.扩展BaseObservable的示例使ViewModel类成为数据类,但应将其作为表示形式类,因为它取代了MVP模式的表示者.

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.

另一件事是ViewModelProviders.of(context).get(Class.class)为每个调用返回相同的ViewModel,它使您可以在视图之间共享相同的数据.

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.

此外,ViewModel类不应包含或包含Android环境中的最少类,并且不应保留对视图类的任何引用,因为它可能会超出视图的寿命.

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);
}

您可以共享布局文件以及如何使用ViewModel类来实现吗?

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

接受的答案中的示例链接不是MVVM和数据绑定的正确示例.

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

第二个示例中的链接集中的ViewModel类:

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));
    }

}

这是数据类,而不是架构组件页面的ViewModel类.指出,它还会导入对单元测试不利的视图类.

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.

这是数据绑定+ RecyclerView教程,此类的正确命名不应为..ViewModel. 查看本教程以了解数据类并将其与RecyclerView绑定.

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.

这篇关于Android体系结构组件:将ViewModel用于RecyclerView项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆