繁体   English   中英

即使数据没有变化,LiveData 观察者的 onChanged 也会在活动轮换时被调用

[英]LiveData observer's onChanged gets called on activity rotation even though there was no change in the data

我正在 Android 应用程序中使用ViewModelsLiveData ,即使屏幕旋转,我也想使用它们来跟踪 Activity 的数据。 这工作得很好,但有一个问题我无法解决。 在 Activity 的onCreate方法中,我为包含对象列表的 LiveData 注册了一个观察者,如果加载了数据,它应该只向 Activity 添加一个 Fragment。 然后,我只在savedInstanceState为 null 时重新加载数据,这应该会在屏幕旋转时阻止它重新加载。 这看起来像这样:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        model = ViewModelProviders.of(this).get(MainActivityModel.class);
        observeList();
        if (savedInstanceState == null) {
            loadList(); //Reload the list and call postValue() on the LiveData.
        }
    }

    private void observeList() {
        model.getList().observe(this, new Observer<ArrayList<Object>>(){
            @Override
            public void onChanged(@Nullable ArrayList<Object> objects) {
                //Add list fragment whenever data changes.
                getSupportFragmentManager().beginTransaction()
                        .replace(R.id.container, ListFragment.getInstance(list))
                        .commit();
            }
        });
    }

我理解它的方式, ListFragment 应该只在数据更改时显示。 但是,经过一些调试,每次屏幕旋转时,observeList 方法中的onChanged方法似乎都会被调用。 此外,我检查了实际列表是否已更改并且完全相同,完全没有区别,甚至从未调用过postValue( ) 或setValue()方法。 因此,我不知道为什么会在屏幕旋转时调用 onChanged 方法。

这也仅在列表包含某些内容时发生。 当应用程序启动时,在调用loadList()之前列表的长度为 0。 当观察者在这个 state 注册时,不会调用 onChanged 方法。

我最好的猜测是onChanged方法被触发是因为当观察者注册时列表不是空的,所以观察者可能认为数据发生了变化。 谁能解释为什么会发生这种情况?

这是按预期工作的。 实时数据概述

确保活动或片段具有可在其变为活动状态后立即显示的数据。 一旦应用程序组件处于 STARTED 状态,它就会从它正在观察的 LiveData 对象接收最新的值。 只有在设置了要观察的 LiveData 对象时才会发生这种情况。

尽管缺少代码片段 - loadList应该是 ViewModel 本身的一部分,而不是一种活动方法。

我遇到了同样的问题,并在此代码实验室中找到了解决方案: Training LiveData

通常,LiveData 仅在数据更改时才向观察者提供更新。 这种行为的一个例外是,当观察者从非活动状态变为活动状态时,观察者也会收到更新。

当 (...) 片段在屏幕旋转后重新创建时,它会从非活动状态变为活动状态。 片段中的观察者重新连接到现有的 ViewModel 并接收当前数据。

所以解决方案基本上是在视图模型中创建一些方法来重置触发观察者的变量的值(在你的情况下,列表)。

当屏幕旋转时,会调用 Activity 生命周期中的以下回调方法

  1. onSaveInstanceState()
  2. 暂停()
  3. 停止()
  4. onCreate()
  5. 开始()
  6. onRestoreInstanceState()
  7. onResume()

如果您记住实时数据观察器是生命周期感知的,这将有所帮助,这意味着它会在 UI 处于活动 state 时进行观察,并在 UI 不在活动 state 时停止观察。 当调用 onStop 方法时,实时数据观察者停止侦听,当再次调用 onCreate 方法时,实时数据观察者再次开始观察。 这就是重新加载观察者的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM