垂直方向にスクロールするrecyclerview(verticalRV)があります。このrecyclerview(horizontalRV)の各アイテムは、Horizontalrecyclerviewです。
VerticalRV itemViewHodler imの内部で、ビューモデルからデータをフェッチし、変更を監視し、それに応じてhorizontalRVアダプターを更新しようとしています。
しかし、オブザーバーはonChanged
メソッドが呼び出されていません。
ライブデータを使用してビューホルダーのライフサイクルを管理し、それに応じてverticalRVのアダプターから状態を設定するために、LifecycleOwnerインターフェイスを実装しました。
public class VeritcalRVHolderItem implements LifecycleOwner {
private static final String TAG = LDFeedListAdapterHolder.class.getSimpleName();
private final FragmentActivity activity;
private final RvHorizontalListAdapter adapter;
private RecyclerView rvHorizontalList;
public VeritcalRVHolderItem(Context context, View itemView, FragmentActivity activity) {
super(context, itemView);
this.activity = activity;
rvHorizontalList = itemView.findViewById(R.id.rvHorizontalList);
LinearLayoutManager layout = new LinearLayoutManager(getContext(), LinearLayout.HORIZONTAL, false);
rvHorizontalList.setLayoutManager(layout);
adapter = new RvHorizontalListAdapter(this.activity);
rvHorizontalList.setAdapter(adapter);
LDViewModel LDViewModel = ViewModelProviders.of(activity).get(LDViewModel.class);
LDViewModel.getTopicsForFeed().observe(this, new Observer<List<Topic>>() {
@Override
public void onChanged(List<Topic> topics) {
//adding live discussion model at first position
adapter.updateLiveList(topics);
adapter.notifyItemChanged(0);
Log.d(TAG, "discussion model calls");
}
});
}
private LifecycleRegistry lifecycleRegistry;
public void onAppear() {
lifecycleRegistry.markState(Lifecycle.State.CREATED);
}
public void onDisappear() {
lifecycleRegistry.markState(Lifecycle.State.DESTROYED);
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
}
ここで何が欠けているのか教えてください。
私の見解では、データをfragment
またはactivity
に観察し、データをrecyclerview
に渡し、Recyclerview
でメソッドgetItemViewType
、getItemViewType
から、vertical
アイテムとhorizontal
アイテムを処理できます。
例:-
public class ViewModel extends AndroidViewModel {
private MutableLiveData<Model> modelMutableLiveData;
public ViewModel(@NonNull Application application) {
super(application);
modelMutableLiveData = new MutableLiveData<>();
}
public MutableLiveData<Model> getModelMutableLiveData() {
return modelMutableLiveData;
}
public final void yourMethod(Model model) {
// Do something
}
}
フラグメントクラス
public class Fragment extend BaseFragment {
private void initViewModelData() {
viewModel.getModelMutableLiveData().observe(this, new Observer<Model>() {
@Override
public void onChanged(@Nullable Model model) {
if (model != null) {
modelList.add(model);
adapter.notifyItemInserted(modelList.size()- 1);
}
}
});
}
}
RecyclerViewAdapter
class RecyclerViewAdater extend Adapter<ViewHolder>{
@Override
public int getItemViewType(int position) {
return mDataList.get(position).getContainerType();
}
}
これに基づいて、recyclerView
コードを書くことができます
この問題には2つのアプローチがあります。1つはShyakの答えです。これは、アダプターの外部の変更を監視し、リストを裏付けるデータの変更を通じて変更を通知します。これは、実際にはリサイクラービューとアダプターのパターンを尊重しています。
ただし、モデルからのデータだけでなく、外部イベントやデータも観察して、recylerviewに表示したい場合があります。集約されたデータを含む新しいモデルでこれらすべての情報を組み合わせる代わりに、アダプター自体で直接変更の一部を観察すると便利な場合があります。
この場合、ViewHolderにオブザーバーを追加し、次のように変更に対応できます。
1)アダプタクラスのコンストラクタにLiveDataを渡します。
class MyAdapter(private var data: LiveData<Int>) :
RecyclerView.Adapter<MyViewHolder>() {
2)viewHolderの作成時にオブザーバーを追加します。
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder
{
val holder = MyViewHolder(
LayoutInflater.from(parent.context).inflate(
R.layout.my_layout, parent,
false
)
)
data.observe(holder.itemView.context as LifecycleOwner, Observer {
.....
// action to be performed by the observer
.....
})
return holder
}
3)viewHolderがモデル要素に関連付けられている場合、viewHolderの正しい視覚状態を設定します
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
if (data.value!! >= 0 && data.value == position)
holder.setSelected(true) // or whatever is visually necessary
else holder.setSelected(false) // or whatever is visually necessary
注意事項:holder.itemView.context as LifecycleOwner
これは基本的に、recyclerviewがライフサイクル所有者であるフラグメント内にあることを意味します。
ViewHolderが再利用されるため、このアプローチは効率的である可能性があるため、リストのさまざまな要素に対して新しいオブザーバーを作成する必要はありません。