アーキテクチャコンポーネントを実験していて、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();
}
}
それは動作しますが、それを行う正しい方法ですか?
おかしいが、答え-これは正しい方法です、受け入れられるべきです:)ハード参照を作成して使用していないので、コードをクリーンアップしてGalleryItemViewModel
からPostViewHolder
を削除できます。次に、onBindViewHolder()
で直接holder.binding.setViewModel(vm);
のように使用します
これは link であり、MVVMコードの例が役立ちます。
まず、ViewModelを正しく実装するには、_Android.Arch.lifecycle.ViewModel
_を拡張する必要があります。 ViewModelクラスをデータクラスにするBaseObservable
を拡張する例ですが、MVPパターンのプレゼンターを置き換えるため、プレゼンテーションクラスにする必要があります。
もう1つは、ViewModelProviders.of(context).get(Class.class)
がすべての呼び出しに対して同じViewModelを返し、ビュー間で同じデータを共有できるようにすることです。
また、ViewModelクラスは、Android環境からの最小クラスを含むべきではありません。また、ビューよりも存続する可能性があるため、ビュークラスへの参照を保持しないでください。
2番目の例では、おそらくアクティビティ/フラグメントから同じViewModelを取得します
_public void setViewModel(GalleryItemViewModel viewModel){
this.viewModel = viewModel;
binding.setViewModel(viewModel);
}
_
レイアウトファイルを共有し、ViewModelクラスでこれを実装する方法を教えてください。
受け入れられた回答のサンプルのリンクは、MVVMおよびデータバインディングの正しい例ではありません。
2番目の例として、リンクセットの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);