これは理論的な質問になります。
誰もがアプリの多くの部分でRecyclerViewを使用しています。 RecyclerViewには、たとえば画像だけでなく、広告やヒントなど、さまざまなアイテムが含まれている場合があります。そのため、AdapterでgetViewType()メソッドを使用できます。
ただし、viewTypeが多数あり、Adapterでこれをバインドするのが適切でない場合に問題が発生します。だからここに質問がありますViewHolderでデータをバインドするのは素晴らしくて良いパターンですか?
アプリのリストがあるとしましょう。
すべてのアプリには、わかりやすい名前が付いています。 ViewHolderは次のようになります。
class AppViewHolder extends RecyclerView.ViewHolder {
public TextView nameText;
AppViewHolder(View itemView) {
super(itemView)
nameText = (TextView) itemView.findViewById(R.id.text_name);
}
}
これでbindメソッドを追加できます:
public void bind(App app) {
nameText.setText(app.getName());
}
いいパターンですか?
別の解決策は、ViewModelを使用することです。 RecyclerViewにはさまざまなアイテムがあるため、アダプターには、すべてのViewModelの基本クラスであるクラスのリストを含めることができます。
したがって、基本的なクラスは次のとおりです。
class RecyclerViewItem {}
アプリのViewModelであるクラスです。
class AppRecyclerViewItem extends RecyclerViewItem {
App app;
...
}
アダプターには、RecyclerViewItemsのリストがあります。
class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
List<RecyclerViewItem> items;
...
}
したがって、このアプローチ(つまり、ViewModelを使用する)では、ViewHolderまたはViewModelにバインドメソッドを追加する方がよいでしょうか?
私はあなたの解決策のどれも良いとは言えません。 1つ目は、アダプターで1回のみ表示されるアイテムにのみ有効です。 ViewHolder
内の行を埋めるメソッドを作成することは、異なるタイプのViewHolders
が大きくなり、RecyclerView.Adapter
がどんどん行を増やすため、良い解決策ではありません。
2番目の方法も良くありません。モデルはモデルです。アプリケーションのビジネスロジックではなく、データのみを含める必要があります。
Ieに登録されるRecyclerView.Adapter
をクリーンに保ち、ViewHolder
を作成してデリゲートにデータを入力するロジックを渡すソリューションを提案します。 RecyclerView.Adapter
コンストラクタ。このテクニックについては、さらに詳しく説明します ここ
このように、さまざまなViewHolder
を1つでも登録しても、RecyclerView.Adapter
に定型文が追加されることはありませんが、RecyclerView.Adapter
行の作成と入力のロジックはこれらのデリゲートに委任されます。
しかし、それは単なる提案です。
デリゲートを使用する優れたソリューションがあります- http://hannesdorfmann.com/Android/adapter-delegates であり、DataBindingにも使用できます(簡単な変更で https:// github。 com/drstranges/DataBinding_For_RecyclerView )。このようにして、ViewHolderおよびRecyclerView Adapterではなく、ItemDelegateでバインドされたデータがこれを行うため、コードは明確で読みやすいままになります。
このアプローチに従うと、すべてがDelegateManagerに委任されたビュータイプで機能します。
public abstract class AbsDelegationAdapter<T> extends RecyclerView.Adapter {
protected AdapterDelegatesManager<T> delegatesManager;
protected T items;
//...
@Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return delegatesManager.onCreateViewHolder(parent, viewType);
}
@Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
delegatesManager.onBindViewHolder(items, position, holder);
}
@Override public int getItemViewType(int position) {
return delegatesManager.getItemViewType(items, position);
}
}
そして、あなたのコードは次のようになります:
mAdapter = new BindableAdapter<>(
new UserDelegate(actionHandler), // you can create custom delegate
//new ModelActionItemDelegate<BaseModel>(actionHandler, User.class, R.layout.item_user, BR.user), // or use generic
new AnotherItemDelegate());
ItemDelegate
は次のようになります。
public class UserDelegate extends BaseAdapterDelegate<BaseModel, ItemUserBinding> {
@Override
public boolean isForViewType(@NonNull final List<BaseModel> items, final int position) {
return items.get(position) instanceof User;
}
@NonNull
@Override
public BindingHolder<ItemUserBinding> onCreateViewHolder(final ViewGroup parent) {
// create ViewHolder
return BindingHolder.newInstance(R.layout.item_user, LayoutInflater.from(parent.getContext()), parent, false);
}
@Override
public void onBindViewHolder(@NonNull final List<BaseModel> items, final int position, @NonNull final BindingHolder<ItemUserBinding> holder) {
// Just bind data
final User user = (User) items.get(position);
holder.getBinding().setUser(user);
}
}
私のアプリでは、次のようなものを使用しています。
public abstract class BindableViewHolder<T> extends RecyclerView.ViewHolder {
public BindableViewHolder(View itemView) {
super(itemView);
}
public abstract void bind(T thing);
}
アイデアはViewHolderへのバインディングの実装を委任するです。このソリューションは、同じ種類のオブジェクトを異なるビューホルダーにバインドする場合を対象としていますが、より一般的なケースに簡単に拡張できると思います。
これは本当に単純なアダプターの例です。私はそれがそれ自身を説明すると思います、それが役立つことを願っています!
public class ShowsAdapter extends RecyclerView.Adapter<BindableViewHolder<Show>> {
private final DataProvider<Show> showsProvider;
public ShowsAdapter(DataProvider<Show> showsProvider) {
this.showsProvider = showsProvider;
}
@Override
public BindableViewHolder<Show> onCreateViewHolder(ViewGroup parent, int viewType) {
return ShowViewHolder.create(parent);
}
@Override
public void onBindViewHolder(BindableViewHolder<Show> holder, int position) {
holder.bind(showsProvider.get(position));
}
@Override
public int getItemCount() {
return showsProvider.size();
}
}
ここで、ShowViewHolderはBindableViewHolderの具象サブクラスです。