android - 我应该独立于 Fragment 的生命周期使用 ViewModelScope 吗?
问题描述
TL;博士
对于片段的一个实例,一次又一次地添加/删除,viewModelScope
在其 ViewModel 中仅在第一次弹出片段之前有效。在此之后,viewModelScope
变为非活动状态。viewModelScope
重新添加片段时如何重新初始化?或者我应该寻找一个更好的实现来保持它的活跃?
设想:
我曾经RxJava
通过ViewModel
在旧项目中从网络检索数据,并将更新发送到 UI,我使用了 LiveData。
以下是我在片段中初始化典型 ViewModel 的方式:
private val fruitsViewModel by viewModels<FruitsViewModel>()
以下是上面提到的 ViewModel:
class FruitsViewModel: ViewModel {
private var category: String = FruitCategories.DEFAULT
private val _fruits = MutableLiveData<List<Fruit>>()
fun fruits(): LiveData<List<Fruit>> = _fruits
fun updateCategory(newCategory: String) {
this.category = newCategory
fetchFruits()
}
fun fetchFruits() { ... }
}
在 Fragment'sonViewCreated()
中,我打电话给fruitsViewModel.fetchFruits()
。这很好用(没有任何明显的问题)。
今天,我用协程切换了 RxJava 特定代码,以在我的 ViewModel 中检索网络数据。像这样的东西:
fun fetchFruits() {
/* this.fruitsJob = */
viewModelScope.launch {
...
}
}
这也很好用,即使在我替换了一个片段并回到它之后。但是,如果我保留在 Activity 中声明的片段实例并再次使用它,viewModelScope.launch {}
则不再起作用。像这样的东西:
class FruitsActivity: AppCompatActivity() {
private val fruitsFragment = FruitsFragment()
private fun showFruitsFragment() {
supportFragmentManager
.beginTransaction()
.replace(getFragmentContainerId(), fruitsFragment)
.addToBackStack(fruitsFragment.tag)
.commit()
}
private fun removeFragments() {
val manager = supportFragmentManager
if (manager.backStackEntryCount > 0) {
val first: FragmentManager.BackStackEntry = manager.getBackStackEntryAt(0)
manager.popBackStack(first.id, FragmentManager.POP_BACK_STACK_INCLUSIVE)
}
}
}
保留片段实例的原因是只加载一次 API 数据,之后,它应该只在单击按钮时出现,没有任何闪烁/加载。
我打电话后removeFragments()
,fruitsViewModel
已经把它叫作保留onCleared()
声明了。因此,它变得不活动,如果我通过调用再次添加,这将不再检索网络数据。我的 Rxjava 实现不是这种情况,因为我没有使用.fruitsFragment
viewModelScope
fruitsFragment
showFruitsFragment()
viewModelScope
我想我可以通过链接fruitsViewModel
到FruitsActivity
's 实例来解决问题。但是,我想知道这是否可以被认为是最好的方法。
解决方案
是的,您应该viewModel
以不同的方式确定范围,在您的情况下确定范围fruitsViewModel
是FruitsActivity
完全有意义的。
我不确定你的RxJava
代码是如何工作的,没有看到我猜测的代码,它与它不disposed
正确有关。
此外,即使您要创建一个范围,该范围比viewModelScope
(例如:CoroutineScope
在活动中创建和维护)我的主要问题是该方法不直观/自然,人们将更难检查CoroutineScope
维护的方式和位置
推荐阅读
- c# - 如何将数据从 listview(sqllite 数据库)导出到 txt 文件?
- windows - 为 PWA 自定义 Windows 10 开始菜单磁贴
- awk - awk 将文件中的字符串与另一个文件匹配并获取前两行和下两行
- linux - 不断从 WSL 上的 Ubuntu 登录不正确
- python - 尝试使用烧瓶套接字库时出现循环导入错误
- css - 基于位置的 Oracle Apex-Color 特定交互式网格单元
- php - 调用未定义函数 json_decode()
- java - 不使用变量时,lambda 表达式中变量名称的约定是什么?
- r - 如何计算 R 中两个数据集的显着差异?
- amazon-web-services - 如何在 AWS 上部署 node-red