这是我的一个奇怪的bug,我开始认为我的片段的观察者在我弹出那个片段后还在观察。
所以,我有两个片段使用相同的viewmodel,但它们并不与活动共享,viewmodel实例是为每个片段而设的
FragmentB()
private val viewModel by viewModels<OrderViewModel> { VMOrderFactory(
OrderRepoImpl(
OrderDataSource()
)
) }
...
viewModel.fetchOrderStatus(trackingDetails.orderId).observe(viewLifecycleOwner, Observer { result -> ... }
现在,我在视图中使用FragmentA() Flow coroutines来保持实时更新。
OrderViewModel
fun fetchOrderStatus(orderId: String) = liveData(Dispatchers.IO){
emit(Resource.Loading())
try{
repo.getOrderStatus(orderId).collect { status ->
emit(status)
}
}catch (e:Exception){
emit(Resource.Failure(e))
}
}
现在,情况是这样的
当我在FragmentA()中时,这可以工作并获取订单。
现在,如果我进入 FragmentB()
并再次回到FragmentA(),尝试从 FragmentA()
与该视图模型的另一个实例和另一个方法,即fetchOrderStatus from FragmentB()
被执行,由于我弹出这个片段,它返回一个nullPointerException。
所以,奇怪的是,使用viewLifeCycleOwner,当回到FragmentA()时,这个观察者并没有从FragmentB()中分离出来,另一个奇怪的事情是,当我迅速从FragmentB()回到FragmentA()并试图删除一个订单时,这种情况就会发生,但如果我稍等一下(2或3秒,直到流连接并请求数据),这种情况就会正常工作。
我的观察者可能发生了什么,发生了什么?
FragmentA()
片段A没有使用FragmentB()的fetchOrderStatus方法。
private val viewModel by viewModels<OrderViewModel> { VMOrderFactory(
OrderRepoImpl(
OrderDataSource()
)
) }
viewModel.deleteOrder(adapter.getItem(position).orderId).observe(viewLifecycleOwner, Observer { result -> ... }
这里抛出了错误,但不是关于deleteOrder方法,而是来自FragmentB()fetchOrderStatus方法,这很奇怪,因为此时FragmentB()被弹出,其方法不应该获取任何数据。
也许我需要在弹出这个fragmentB时杀死流,但我是在datasource方法处做的,当它获取并交付时,用的是
awaitClose { subscription.remove() }
如果你创建ViewModel并提供Fragment上下文,那么当Fragment被销毁时,ViewModel就会被销毁。如果你想让ViewModel的寿命超过片段,那么你需要用活动上下文来启动它。activityViewModel()