无需配置视图模型即可通过配置更改保留CoroutineScope的干净方法

问题描述 投票:4回答:2

我知道建议将ViewModel与我们的Activity一起使用,因此我们可以使用其viewModelScope。由于ViewModel的寿命超过了Activity,因此我们不必取消activity.onDestroy()中的工作。

但是,有时您的活动很简单。例如,它可以使用已安装的已过滤软件包填充列表视图。您可以非常简单地使用委托为活动创建范围,并在onDestroy()中取消作业:

class MyActivity(): AppCompatActivity(), CoroutineScope by MainScope() {

    private val listAdapter = MyAdapter()

    override fun onCreate() {
        super.onCreate()
        setContentView(R.layout.my_activity)
        recycler_view.apply {
            layoutManager = LinearLayoutManager(this)
            adapter = listAdapter
        }
        launch {
            val packages = getOrgPackagesWithIcons()
            adapter.apply {
                data = packages
                notifyDataSetChanged()
            }
        }

    }

    override fun onDestroy() {
        super.onDestroy()
        cancel() // CoroutineContext
    }

    private suspend fun getOrgPackagesWithIcons() = withContext(Dispatchers.Default) {
        var toNextYield = 20
        packageManager.getInstalledPackages(0)
            .filter { it.packageName.startsWith("org")
            .take(100)
            .map { 
                     if (--toNextYield == 0) { // Make it cancellable
                         toNextYield = 20
                         yield()
                     }
                     MyPackageData(
                         it.applicationInfo.loadLabel(packageManager).toString(),
                         it.packageName,
                         it.applicationInfo.loadIcon(packageManager)
                     )
                 }
        }

}

对于这种情况,ViewModel感觉像是过分杀伤力。这将是抽象PackageManager的另一层,它实际上是一个视图模型。

上面的代码使在后台组装数据变得容易。问题在于,当旋转屏幕或进行其他配置更改时,协程将被取消并重新启动。是否有一个干净的方法可以通过更改配置来使CoroutineScope保持活动状态,例如一个非常简单的Activity?

onRetainNonConfigurationInstance()已过时。我想我们可以将其放在Fragment中并使用retainInstance = true,但是将Fragment层引入到如此简单的Activity中也感觉像是过分杀伤。

也许有一种方法可以创建一个空的ViewModel实现,以便我们可以借用它的作用域?

android kotlin kotlin-coroutines
2个回答
3
投票

对于这种情况,ViewModel感觉像是过分杀伤。

我会反驳,但仍然建议这是AndroidViewModel的好用例。

我相信,AndroidViewModel并不是仅仅因为它有权访问Activity而获取包裹清单。 PackageManager仅应负责显示列表。

使用Activity使您可以访问AndroidViewModel实例中的ContextviewModelScope


0
投票

同意以上答案,因为这里执行的数据操作实际上并不属于该活动,所以ViewModel仍然是此处的最佳选择。就是说,如果您查看how ViewModel保留数据-它的简单静态值。这里没有引用完整的链,只是引用了所有部分的组合]

ViewModel

其中NonConfigurationInstances是:

if (mViewModelStore == null) {
    NonConfigurationInstances nc =
            (NonConfigurationInstances) getLastNonConfigurationInstance();
    if (nc != null) {
        // Restore the ViewModelStore from NonConfigurationInstances
        mViewModelStore = nc.viewModelStore;
    }
    if (mViewModelStore == null) {
        mViewModelStore = new ViewModelStore();
    }
}

将其放在此处以解决您的问题,即“清空ViewModel实现”,这是在那里完成的方式,您可以做类似的事情-也许放在您自己的Application类中。但是,话又说回来,它就在那儿,使用起来很简单,并提供了其他好处...所以我总是使用视图模型/ androidviewmodel,我的脑子里根本没有开销,相反,代码组织得很好。

© www.soinside.com 2019 - 2024. All rights reserved.