【问题标题】:Weird AndroidViewModel LiveData observer behaviour奇怪的 AndroidViewModel LiveData 观察者行为
【发布时间】:2018-10-23 13:58:44
【问题描述】:

我说奇怪是因为我不明白有人可能会告诉我什么正在按预期工作。

我有一个带有 LiveData 成员的 AndroidViewModel,我在 MainActivity 中观察到它可以切换一些代码功能。 LiveData 对象在视图模型的构造函数中被分配了初始值。

理论上一切正常,除了观察者的行为在安装后首次启动应用程序和后续应用程序启动之间发生变化。

在安装后的第一次启动期间,观察者在我设置它们后立即被触发,而底层的 LiveData 对象没有被更改。

在应用程序的后续启动期间,观察者不会在设置后过早触发,而是仅在我更改应用程序其他地方的值时触发,这是我期望发生的。

最初我认为观察者不知何故从 LiveData 初始化中获得了延迟触发,但如果这是真的,那么无论是安装后的第一次运行还是后续启动,它都应该发生。

因此,为了让应用按预期运行,如果应用在安装后首次运行,我必须在观察者中使用哨兵,以防止它们在第一次触发期间正常运行。

有人可以解释为什么会发生这种情况,如果它是我不相信的预期功能,请指向解释此问题的文档?

我觉得我又在破解 Android。

这是人们经常要求的一些代码 sn-ps,从 LiveData 声明开始。

@NonNull
private final MutableLiveData<Boolean> consentRequired = new MutableLiveData<>();

ViewModel 构造函数初始化

    setConsentRequired(false);

ViewModel 获取器/设置器

@NonNull
public LiveData<Boolean> getConsentRequired()
{
    return consentRequired;
}
@NonNull
public void setConsentRequired(@NonNull Boolean consentRequired)
{
    this.consentRequired.setValue(consentRequired);
}

观察者

    getViewModel().getConsentRequired().observe(this, item ->
    {
        if (sentryAllowsObserverToRun)
        {
            // Do the observer stuff here
        }
    }

sentryAllowsObserverToRun 是我必须设置的布尔值,以表明这不是安装后首次应用启动的第一个触发器。

【问题讨论】:

  • 从viewmodel setConsentRequired(false)的构造函数中移除这个调用;
  • @Vishal 谢谢,我知道是构造函数分配触发了第一次观察,但我想知道为什么这只发生在设备上安装应用程序后的第一次启动时,并且永远不会对于任何其他应用程序启动。因此,当应用程序安装并启动时,构造函数赋值会触发观察者,然后我关闭应用程序,当我再次运行应用程序时,构造函数赋值不会触发观察者。这种行为很奇怪。
  • 因为 ViewModelProviders 返回 ViewModel 的单例对象,这意味着当您启动应用程序时,ViewModelProviders 会创建一个对象,并且每当您在应用程序的同一生命周期期间访问该对象时,它都会返回相同的对象。
  • @Vishal 你没抓住重点。我关闭了应用程序,所以它的生命周期不一样。让我这样说吧。我安装了应用程序,当我打开它时,观察者立即被触发。然后我关闭应用程序,关闭手机。当我重新打开手机并打开应用程序时,不会触发观察者。没有生命周期可以在冷启动设备后存活。仅当我安装后第一次运行应用程序时才会触发观察者。

标签: android android-livedata android-viewmodel


【解决方案1】:

问题的答案在此注释中:

...观察者从非活动状态变为活动状态时也会收到更新。此外,如果观察者第二次从非活动状态变为活动状态,则只有在自上次变为活动状态后值发生变化时,它才会收到更新。

在您的情况下,consentRequired 具有 新数据(在 vm 构造函数中分配),当您的 MainActivity 开始观察数据并变为活动状态时,consentRequired 将数据传递给 MainActivity。 要解决它,您需要避免将临时初始数据设置为LiveData

我想,“关闭应用程序”实际上是指“最小化应用程序”。在这种情况下,应用程序进程保持活动状态,并且活动进入后台状态。直到活动保持在回溯中,视图模型也保持在内存中。当您“重新打开应用程序”时,活动返回前台状态,但文档说:

此外,如果观察者第二次从非活动状态变为活动状态,它只会在自上次激活后值发生变化时才会收到更新。

这会导致:当您的活动保留在后台堆栈中并且LiveData 的值保持不变时,您的活动将不会接收数据。

您可以阅读文档的Observe LiveData objects 段落中的示例详细说明。

【讨论】:

  • 昨晚我自己读到了,所以感谢您确认我的新理解。但是我仍然不明白为什么只有在设备上安装应用程序后第一次触发构造函数分配。构造函数分配永远不会触发任何后续应用启动的观察者。
  • @nobodyspecial 你能澄清一下,我如何重现“从不触发任何后续应用启动的观察者”一步一步
  • (1) 安装应用打开应用,立即触发观察者,然后关闭应用。 (2) 关闭后打开应用,观察者不会被触发。反复关闭和​​重新打开应用程序永远不会触发观察者。 (3) 删除应用的存储,模拟全新安装,打开应用立即触发观察者。
  • @nobodyspecial 我已经补充了答案。它应该可以帮助你
  • 不,我不是说最小化,我是说关闭。如果我关闭手机就会发生这种情况,这就是我不明白的原因。我现在已经重构了我的代码,不使用观察者来实现我所需的功能,我不能再浪费时间试图破解这个 ViewModel/LiveData 问题了。我将尝试在以后的测试程序中回到这一点,以了解发生了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-18
相关资源
最近更新 更多