簡體   English   中英

Android架構組件:使用ViewModel for RecyclerView項目

[英]Android Architecture Components: using ViewModel for RecyclerView items

我正在嘗試使用Architecture Components,我想為RecyclerView的每個項目構建一個ViewModel。 我不確定這是否正式正確或我應該堅持“舊方式”。

我有這個適配器:

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關聯? 甚至可能嗎?

編輯:玩它,我試圖通過以下方式放入ViewModels:

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

它有效,但這是正確的方法嗎?

有趣,但回答 - 這是正確的方法,應該被接受:)你可以做一些代碼清理並從PostViewHolder刪除GalleryItemViewModel ,因為你正在創建硬引用而不是使用它。 然后在onBindViewHolder()使用它就像holder.binding.setViewModel(vm);

這是一個可以幫助您的MVVM代碼示例的鏈接

首先,正確實現ViewModel應該是通過擴展android.arch.lifecycle.ViewModel 擴展BaseObservable的示例使ViewModel類成為一個數據類,但它應該是表示類,因為它取代了MVP模式的演示者。

另一件事是ViewModelProviders.of(context).get(Class.class)為每個調用返回相同的ViewModel,它允許您在視圖之間共享相同的數據。

此外,ViewModel類不應該包含Android環境中的最小類,也不應該保留對視圖類的任何引用,因為它可能比視圖更長。

在第二個示例中,您可能使用Activity / Fragment獲取相同的ViewModel

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

你可以共享布局文件以及如何使用ViewModel類實現它嗎?

接受答案中的樣本鏈接不是MVVM和數據綁定的正確示例。

ViewModel類從鏈接集中作為第二個示例:

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類,它還導入了對單元測試不利的視圖類。

它的數據綁定+ RecyclerView教程,正確的命名不應該是這個類的..ViewModel。 查看本教程中的數據類並將其與RecyclerView綁定。

確保在獲取ViewModel時分配唯一標識符,因為ViewModelProviders會為您提供相同的實例,否則

get( 一些唯一的id ,GalleryItemViewModel.class);

所以請嘗試在那里添加ID,如下所示:

 GalleryItemViewModel vm = ViewModelProviders.of((FragmentActivity) holder.getContext()).get(**some unique id**, GalleryItemViewModel.class);
    vm.setPost(list.get(position));
    holder.setViewModel(vm);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM