即使数据没有变化,LiveData 观察者的 onChanged 也会在活动轮换时被调用 [英] LiveData observer's onChanged gets called on activity rotation even though there was no change in the data

查看:54
本文介绍了即使数据没有变化,LiveData 观察者的 onChanged 也会在活动轮换时被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm working with ViewModels and LiveData in an Android app, and I want to use them to keep track of data for an Activity even when the screen is rotated. This works quite well, but there's one issue I can't fix. In the Activity's onCreate method, I register an observer for a LiveData containing a list of objects, which should just add a Fragment to the activity if the data is loaded. Then, I only reload the data if savedInstanceState is null, which should stop it from being reloaded in the event of a screen rotation. This looks like this:

    @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 方法.

The way I understand it, the ListFragment should only be shown when data changes. However, after some debugging, it seems the onChanged method in the observeList method gets called every single time the screen is rotated. Additionally, I checked whether the actual list was changed and it was exactly the same, no difference at all and there was never even a postValue() or setValue() method call. Therefore, I have no idea why the onChanged method would be called on screen rotation.

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

This also only happens when the list contains something. When the app is started up, the list has a length of 0 before loadList() is called. When the observer is registered at this state, the onChanged method is not called.

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

My best guess is that the onChanged method gets triggered either because the list is not empty when the observer is registered so the observer could think there is a change in data. Can anyone explain why this might be happening?

推荐答案

这是按预期工作的.来自 livedata 概览:

This is working as intended. From livedata overview:

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

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 本身的一部分,而不是一种活动方法.

Although there's missing code snippets - loadList should be a part of ViewModel itself, not a method of activity.

这篇关于即使数据没有变化,LiveData 观察者的 onChanged 也会在活动轮换时被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆