如何将LiveData和ViewModel与具有作为生命周期所有者的Viewholder一起使用?

时间:2019-02-22 10:58:48

标签: android mvvm android-recyclerview viewmodel android-livedata

我有一个recyclerview(verticalRV),它可以垂直滚动。 此recyclerview(horizo​​ntalRV)中的每个项目都是水平recyclerview。

在verticalRV itemViewHodler内部,我试图从视图模型中获取数据并观察是否有任何变化,并相应地更新horizo​​ntalRV适配器。

但是观察者是onChanged方法没有被调用。

我已经实现了LifecycleOwner接口,以使用livedata管理视图持有者的生命周期,并通过verticalRV的适配器相应地设置状态

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

}

请让我知道我在这里想念的是什么。

2 个答案:

答案 0 :(得分:0)

从我的角度来看,最好将数据观察到fragmentactivity中并将数据传递给recyclerview,在Recyclerview中重写方法{{1} },您可以从getItemViewType处理getItemViewTypevertical项目。

示例:-

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

RecyclerViewAdapter

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

基于此,您可以编写您的 class RecyclerViewAdater extend Adapter<ViewHolder>{ @Override public int getItemViewType(int position) { return mDataList.get(position).getContainerType(); } } 代码

答案 1 :(得分:0)

有两种方法可以解决该问题,一种是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,因此这种方法非常有效,因此我们不必为列表的各个元素创建新的观察者。