Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 我是否应该使用独立于片段的ViewModelScope';生命周期?_Android_Android Fragments_Kotlin Coroutines_Android Viewmodel - Fatal编程技术网

Android 我是否应该使用独立于片段的ViewModelScope';生命周期?

Android 我是否应该使用独立于片段的ViewModelScope';生命周期?,android,android-fragments,kotlin-coroutines,android-viewmodel,Android,Android Fragments,Kotlin Coroutines,Android Viewmodel,TL;博士 对于一个片段的一个实例,它被一次又一次地添加/删除,其ViewModel中的viewModelScope仅在第一次弹出片段之前有效。在此之后,viewModelScope变为非活动状态。当我重新添加片段时,如何重新初始化viewModelScope?或者我应该寻找更好的实现来保持它的活动性 情景: 我使用RxJava通过ViewModel从旧项目的网络中检索数据,并将更新发送到UI,我使用了LiveData 以下是我如何在片段中初始化典型的ViewModel: private val

TL;博士

对于一个片段的一个实例,它被一次又一次地添加/删除,其ViewModel中的
viewModelScope
仅在第一次弹出片段之前有效。在此之后,
viewModelScope
变为非活动状态。当我重新添加片段时,如何重新初始化
viewModelScope
?或者我应该寻找更好的实现来保持它的活动性

情景:

我使用
RxJava
通过
ViewModel
从旧项目的网络中检索数据,并将更新发送到UI,我使用了LiveData

以下是我如何在片段中初始化典型的ViewModel:

private val fruitsViewModel by viewModels<FruitsViewModel>()
这也很好,即使在我替换了一个片段并返回到它之后。但是,如果我在活动中声明了一个片段实例,并再次使用它,
viewModelScope.launch{}
将不再工作。大概是这样的:

fun fetchFruits() {

    /* this.fruitsJob = */ 
    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()
来保存
fruitsffragments
的声明。因此,它的
viewModelScope
变为非活动状态,如果我通过调用
showfruitsfracent()
再次添加
fruitsfracent
,这将不再检索网络数据。我的Rxjava实现并非如此,因为我没有使用
viewModelScope


我想我可以通过将
fruitsViewModel
链接到
FruitsActivity
的实例来解决这个问题。但是,我想知道这是否是最好的方法。

是的,您应该以不同的方式确定
视图模型的范围,在您的情况下,将
水果视图模型
的范围限定为
水果活动
是完全有意义的

我不确定你的
RxJava
代码是如何工作的,如果没有看到我猜测的代码,那与
处理不正确有关


此外,即使您要创建一个超出
viewModelScope
的范围(例如:在活动中创建并维护
CoroutineScope
),我的主要问题是,这种方法是不直观/自然的,人们将很难检查如何和在哪里维护
CoroutineScope
保持片段实例的原因是只加载一次API数据
,因此听起来您需要一个共享视图模型,不是吗?为什么不将视图模型附加到活动并让它进行服务调用,因为您需要与@a_local_nobody协商。由于无论附加和分离了多少次,片段都会保留更长的时间(类似于活动的生存期),因此最好使用活动的范围或活动的视图模型。顺便说一句,因为您希望独立于片段的生命周期保留加载的数据,数据应该存储在活动中,而不是片段中。在国际海事组织,保留碎片实例不是一个好的做法。同意,谢谢。p、 与美国RxJava相关的实现处理了ViewModel的
onCleared()
方法中的所有可处置项。这允许在onCleared()之后进行新调用,因为RxJava没有链接到任何生命周期。但是,对于协同路由,我依赖于链接到生命周期(?)的
viewModelScope
。嗯,我想知道实现有什么不同,因为从技术上讲
viewModelScope
取消
onCleared()处的协同路由。
RxJava实现不依赖于协同路由或
viewModelScope
fetchFruits()
就像任何其他类中的方法一样。
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)
        }
    }
}