ViewModel没有释放观察者并导致nullpointerexceptions

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

这是我遇到的一个奇怪的错误,我开始认为我的片段的观察者在弹出该片段后仍在观察。

所以,我有两个使用相同视图模型的片段,但它们不与活动共享,每个片段的viewmodel实例都是

FragmentB()

   private val viewModel by viewModels<OrderViewModel> { VMOrderFactory(
            OrderRepoImpl(
                OrderDataSource()
            )
        ) }
  ...

           viewModel.fetchOrderStatus(trackingDetails.orderId).observe(viewLifecycleOwner, Observer { result -> ... }

现在,我使用FragmentA()Flow协程在我的视图中实时保持更新。

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()中删除,则将执行FragmentB()中的fetchOrderStatus,因为我弹出了这个片段返回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时,我需要杀死流,但是当它获取并交付时,我正在使用数据源方法来完成它]

  awaitClose { subscription.remove() }

这是我遇到的一个奇怪的错误,我开始认为我弹出该片段后,该片段的观察者仍在观察。因此,我有两个使用相同视图模型的片段,但它们不...

android android-fragments kotlin viewmodel android-architecture-components
1个回答
0
投票

如果创建ViewModel并提供Fragment上下文,则在销毁Fragment后销毁ViewModel。如果您希望ViewModel超出片段的寿命,则需要以活动上下文activityViewModel()

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