查看Recycler的模型查看项目 [英] View models for RecyclerView items

查看:74
本文介绍了查看Recycler的模型查看项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的活动有一个Google的ViewModel,它可以获取一些模型项.然后将这些项目转换为RecyclerView的适配器项目.一个RecyclerView支持多种适配器项目.

My activity has a Google's ViewModel that fetches some model items. These items are then transformed into adapter items of a RecyclerView. There are also many types of adapter items supported by one RecyclerView.

我希望每个模型对象都有一个单独的视图模型对象,这样我才可以将更复杂的逻辑封装在该小"视图模型中.

I would like to have separate view model object for each of these model objects so that I can have more complex logic encapsulated only within that "small" view model.

当前,当我有一些仅与某些适配器项有关的异步逻辑(需要在onCleared()中停止)时,我必须以某种方式通过主视图模型路由回调,以便正确地注销所有内容.

Currently when I have some asynchronous logic (that needs to be stopped in onCleared()) that is related only to some adapter item I have to somehow route callbacks through main view model so that everything is properly unregistered.

我当时正在考虑使用 ViewModelProvider :: get(key,modelClass),但是我的商品随着时间的推移而变化,我找不到一种清除"旧商品的好方法.

I was considering using ViewModelProvider::get(key, modelClass) but my items are changing over time and I can't find a nice way to "clear" old items.

您如何在项目中处理这些情况?

How are you handling these cases in your projects?

要添加有关我的关注的更多信息,也许用不同的词:我希望我的小" ViewModel能够与它代表的模型项一样长.这意味着:

To add more information about my concern, maybe in different words: I want my "small" ViewModel to live as long as the model item which it represents. It means that:

  • 在这些项的父项接收相同的情况下,我必须接收onCleared()回调
  • 项目不再存在时,我必须接收onCleared()回调

请尝试将其与以片段"作为项目的ViewPager进行比较.每个单独的模型项均使用其ViewModel表示为片段.我想为RecyclerView实现类似的功能.

Please try to compare it to a ViewPager with Fragments as items. Every individual model item is represented as a Fragment with its ViewModel. I would like achieve something similar but for RecyclerView.

推荐答案

不知道google是否对嵌套ViewModel很好地支持.值得庆幸的是,我们不需要坚持使用 androidx.lifecycle.ViewModel 在需要的地方应用MVVM方法.我决定写一个小例子:

Don't know if google has nice support for nested ViewModel's, looks like not. Thankfully, we don't need to stick to androidx.lifecycle.ViewModel to apply MVVM approach where we need. And there is a small example I decided to write:

片段,没有任何变化:

    @Override public void onCreate(@Nullable Bundle savedInstanceState) {
        final ItemListAdapter adapter = new ItemListAdapter();
        binding.getRoot().setAdapter(adapter);

        viewModel = new ViewModelProvider(this).get(ItemListViewModel.class);
        viewModel.getItems().observe(getViewLifecycleOwner(), adapter::submitList);
    }

ItemListAdapter ,除了填充视图外,它还负责通知项目的观察者-是否继续听.在我的示例适配器中,ListAdapter扩展了RecyclerView.Adapter,因此它接收项目列表.这是无意的,只是编辑了一些我已经拥有的代码.使用不同的基本实现可能要好得多,但出于演示目的是可以接受的:

ItemListAdapter, in addition to populate view, it also becomes responsible for notifying item's observers - should they continue to listen, or not. In my example adapter was ListAdapter which extends RecyclerView.Adapter, so it receives list of items. This is unintentionally, just edited some code I already have. It's probably much better to use different base implementation, but it's acceptable for demonstration purposes:

    @Override public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new Holder(parent);
    }

    @Override public void onBindViewHolder(Holder holder, int position) {
        holder.lifecycle.setCurrentState(Lifecycle.State.RESUMED);
        holder.bind(getItem(position));
    }

    @Override public void onViewRecycled(Holder holder) {
        holder.lifecycle.setCurrentState(Lifecycle.State.DESTROYED);
    }

    // Idk, but these both may be used to pause/resume, while bind/recycle for start/stop.
    @Override public void onViewAttachedToWindow(Holder holder) { }
    @Override public void onViewDetachedFromWindow(Holder holder) { }

Holder.它实现了LifecycleOwner,它可以自动取消订阅,只需从 androidx.activity.ComponentActivity 源复制过来,一切就可以了:D:

Holder. It implements LifecycleOwner, which allows to unsubscribe automatically, just copied from androidx.activity.ComponentActivity sources so all should be okay :D :

static class Holder extends RecyclerView.Holder implements LifecycleOwner {

    /*pkg*/ LifecycleRegistry lifecycle = new LifecycleRegistry(this);

    /*pkg*/ Holder(ViewGroup parent) { /* creating holder using parent's context */ }

    /*pkg*/ void bind(ItemViewModel viewModel) {
        viewModel.getItem().observe(this, binding.text1::setText);
    }

    @Override public Lifecycle getLifecycle() { return lifecycle; }
}

列表视图模型,分类";androidx-ish ViewModel,但非常粗糙,还提供了嵌套的视图模型.请注意,在此示例中,所有视图模型都将立即在构造函数中运行,直到命令清除父视图模型为止!不要在家尝试!

List view-model, "classique" androidx-ish ViewModel, but very rough, also provide nested view models. Please, pay attention, in this sample all view-models start to operate immediately, in constructor, until parent view-model is commanded to clear! Don't Try This at Home!

public class ItemListViewModel extends ViewModel {

    private final MutableLiveData<List<ItemViewModel>> items = new MutableLiveData<>();

    public ItemListViewModel() {
        final List<String> list = Items.getInstance().getItems();

        // create "nested" view-models which start background job immediately
        final List<ItemViewModel> itemsViewModels = list.stream()
                .map(ItemViewModel::new)
                .collect(Collectors.toList());

        items.setValue(itemsViewModels);
    }

    public LiveData<List<ItemViewModel>> getItems() { return items; }

    @Override protected void onCleared() {
        // need to clean nested view-models, otherwise...
        items.getValue().stream().forEach(ItemViewModel::cancel);
    }
}

Item的视图模型,使用一些rxJava模拟了一些后台工作和更新.我故意地没有将其实现为 androidx .... ViewModel ,只是为了强调视图模型不是Google命名为ViewModel而是行为为ViewModel的模型.在实际程序中,它很可能会扩展,但是:

Item's view-model, using a bit of rxJava to simulate some background work and updates. Intentionally I do not implement it as androidx....ViewModel, just to highlight that view-model is not what google names ViewModel but what behaves as view-model. In actual program it most likely will extend, though:

// Wow, we can implement ViewModel without androidx.lifecycle.ViewModel, that's cool!
public class ItemViewModel {

    private final MutableLiveData<String> item = new MutableLiveData<>();

    private final AtomicReference<Disposable> work = new AtomicReference<>();

    public ItemViewModel(String topicInitial) {
        item.setValue(topicInitial);
        // start updating ViewModel right now :D
        DisposableHelper.set(work, Observable
            .interval((long) (Math.random() * 5 + 1), TimeUnit.SECONDS)
                    .map(i -> topicInitial + " " + (int) (Math.random() * 100) )
                    .subscribe(item::postValue));
    }

    public LiveData<String> getItem() { return item; }

    public void cancel() {
        DisposableHelper.dispose(work);
    }

}

此示例中的注释很少:

  • 父母"ViewModel位于活动范围内,因此其所有数据(嵌套视图模型)也是如此.
  • 在此示例中, all 嵌套的vm开始立即运行.这不是我们想要的.我们要相应地修改构造函数,onBind,onRecycle和相关方法.
  • 请对内存泄漏进行测试.
  • "Parent" ViewModel lives in activity scope, so all its data (nested view models) as well.
  • In this example all nested vm start to operate immediately. Which is not what we want. We want to modify constructors, onBind, onRecycle and related methods accordingly.
  • Please, test it on memory leaks.

这篇关于查看Recycler的模型查看项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆