LiveData 观察者的 onChanged 在 activity 旋转时被调用,即使数据没有变化

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 添加一个片段。然后,我只在 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。该状态注册观察者时,不会调用onChanged方法

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

这是按预期工作的。来自 livedata overview:

To ensure that the activity or fragment has data that it can display as soon as it becomes active. As soon as an app component is in the STARTED state, it receives the most recent value from the LiveData objects it’s observing. This only occurs if the LiveData object to be observed has been set.

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

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

Usually, LiveData delivers updates to the observers only when data changes. An exception to this behavior is that observers also receive updates when the observer changes from an inactive to an active state.

When the (...) fragment is re-created after a screen rotation, it moves from an inactive to an active state. The observer in the fragment is re-connected to the existing ViewModel and receives the current data.

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