Search code examples
androidviewmodelandroid-livedata

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


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

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.

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.

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?


Solution

  • This is working as intended. From 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.

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