我知道建议将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实现,以便我们可以借用它的作用域?
对于这种情况,ViewModel感觉像是过分杀伤。
我会反驳,但仍然建议这是AndroidViewModel
的好用例。
我相信,AndroidViewModel
并不是仅仅因为它有权访问Activity
而获取包裹清单。 PackageManager
仅应负责显示列表。
使用Activity
使您可以访问AndroidViewModel
实例中的Context
和viewModelScope
。
同意以上答案,因为这里执行的数据操作实际上并不属于该活动,所以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,我的脑子里根本没有开销,相反,代码组织得很好。