【问题标题】:ViewModel not detaching observer and causing nullpointerexceptionsViewModel 没有分离观察者并导致空指针异常
【发布时间】:2020-04-12 14:22:43
【问题描述】:

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

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

片段B()

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

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

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

订单视图模型

 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 秒,直到流程附加并请求数据),这将正常工作

可能会发生什么以及我的观察者会发生什么?

片段A()

Fragment 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() }

【问题讨论】:

  • 在fragment的什么方法里面附加观察者?
  • 在 onViewCreated() @Pawel 内

标签: android android-fragments kotlin viewmodel android-architecture-components


【解决方案1】:

如果您创建 ViewModel 并提供 Fragment 上下文,则 ViewModel 会在 Fragment 被销毁时被销毁。如果您希望 ViewModel 比 Fragments 更长寿,那么您需要使用活动上下文 activityViewModel() 启动它

【讨论】:

  • 但这不是我问的
  • 也许问题不在于片段生命周期和观察者,而在于您的流程实现。如果您删除流程代码并将日志放在 fetch 方法中,它是否工作相同? liveData(Dispatchers.IO) 里面是什么?也许这是该库中的一个错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-02
  • 1970-01-01
  • 1970-01-01
  • 2014-08-02
  • 2015-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多