如何手动清除特定的视图模型? [英] How to manually clear a specific viewmodel?

查看:112
本文介绍了如何手动清除特定的视图模型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我了解,当我们在片段中调用此代码时,我们将从活动ViewModelStore中获得一个viewmodel实例:

As I understand when we call this code in fragments, we will have a viewmodel instance from activity ViewModelStore:

viewModel = ViewModelProviders.of(activity!!).get(SharedViewModel::class.java)

当片段将终止其生命周期时,此Viewmodel的实例将存在于ViewModelStore中,直到活动被破坏为止. ViewModelStore有一个clear()方法,但它会清除其中的所有视图模型.有什么方法可以清除特定的ViewModel?

When fragments will end their lifecycle, the instance of this viewmodel will exist in ViewModelStore until the destruction of activity. ViewModelStore has a clear() method, but it clears all viewmodels in it. Is there some way to clear specific ViewModel?

另一个解决方案是将ViewModel的作用域限定为父片段,但是如何通过ViewModelProviders.of()在另一个片段中初始化ViewModel?我应该将片段或viewmodel实例传递给下一个片段吗?

Another solution is to scope ViewModel to parent fragment, but how do we initialize ViewModel in another fragment through ViewModelProviders.of()? Should I pass fragment or viewmodel instance to the next fragment?

推荐答案

有一种清除特定ViewModel实例的简单方法,您应在其中使用自定义的key创建您的ViewModel实例,如下所述,为了清除它,您应该创建另一个实例(具有不同的ViewModel类,例如EmptyViewModel类),但是具有相同的key.

There is a hacky way to clear a specific ViewModel instance in which you should create your ViewModel instance with a customized key as stated below, and in order to clear it you should just create another instance (with different ViewModel class such as an EmptyViewModel class) but with the same key.

ShopFragment类:

ShopFragment class:

class shopFragment : BaseFragment() {

    fun getViewModel() : ShopViewModel {
        return ViewModelProviders.of(activity!!).get(ShopViewModel.KEY, ShopViewModel::class.java)
    }

    fun clearViewModel() {
        ViewModelProviders.of(activity!!).get(ShopViewModel.KEY, EmptyViewModel::class.java) 
    }

    // Fragment logic ...

}

ShopViewModel类:

ShopViewModel class:

class ShopViewModel(application: Application) : AndroidViewModel(application) {

    companion object {
        const val KEY = "ShopViewModel"
    }

    // view model logic ...

}

EmptyViewModel,它是一个虚拟的ViewModel类:

EmptyViewModel which is a dummy ViewModel class:

class EmptyViewModel() : ViewModel() {
    // A dummy view model!
}

魔术发生在androidx.lifecycle dependecy的ViewModelProvider类内部,当您查看ViewModelProvider类的get()函数时,这里的技巧就揭示出来,该函数检索您以前的ViewModel实例并进行比较它与EmptyViewModel类一起使用,并且由于它们不相同,因此运行mViewModelStore.put(key, viewModel);:

And the magic is happening inside ViewModelProvider class of androidx.lifecycle dependecy, the trick here is revealed when you take a look at the get() function of ViewModelProvider class which retrieves your previous ViewModel instance and compares it with the EmptyViewModel class and as they are not the same, it run mViewModelStore.put(key, viewModel);:

public class ViewModelProvider {
//...
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {
        ViewModel viewModel = mViewModelStore.get(key);

        if (modelClass.isInstance(viewModel)) {
            //noinspection unchecked
            return (T) viewModel;
        } else {
            //noinspection StatementWithEmptyBody
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }

        viewModel = mFactory.create(modelClass);
        mViewModelStore.put(key, viewModel);
        //noinspection unchecked
        return (T) viewModel;
    }
// ...
}

如下所述,在androidx.lifecycle依赖项的ViewModelStore类中,put()方法将检索ShopViewModel并将其清除,并替换EmptyViewModel实例.

As stated below inside ViewModelStore class of the androidx.lifecycle dependency, the put() method will retrieve the ShopViewModel and clear it, and replace EmptyViewModel instance.

public class ViewModelStore {
    //...
    final void put(String key, ViewModel viewModel) {
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }
    //...
}

这篇关于如何手动清除特定的视图模型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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