ViewModel没有脱离观察者,导致nullpointerexceptions。

问题描述 投票:0回答:1

这是我的一个奇怪的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() }
android android-fragments kotlin viewmodel android-architecture-components
1个回答
-1
投票

如果你创建ViewModel并提供Fragment上下文,那么当Fragment被销毁时,ViewModel就会被销毁。如果你想让ViewModel的寿命超过片段,那么你需要用活动上下文来启动它。activityViewModel()

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