varunkr
varunkr

Reputation: 5542

MediatorLiveData onChanged not getting called

In my app I am trying to use MediatorLiveData to listen to the changes to a livedata. Since DB operations are involved I use an executor service like this.

    MediatorLiveData<Content> mediatorLiveData = new MediatorLiveData<>();
    appExecutors.diskIO().execute(() -> {
                    long id = contentDao.insert(content);
                    Log.i("LIVE", id + "");
                    LiveData<Content> content = contentDao.getContentById(id);

                    mediatorLiveData.addSource(content, new Observer<Content>() {
                        @Override
                        public void onChanged(@Nullable Content content) {
                            Log.i("LIVE", "FIRED");
                        }
                    });

                });

First I try to insert a new content object into the db. I get the id of the inserted object which I log in the next line. I get some id which is good. After this, I use the id to query for the same object. The query returns a LiveData. (If I use content.getValue() at this time, I get null.)

Then I listen to changes in this liveData using a MediatorLiveData. Unfortunately, the onChange method of the mediatorLiveData is never fired. Thus the Log is not printed too.

This is my content dao class

@Dao
public interface ContentDao {

    @Insert
    long insert(Content content);

    @Query("SELECT * FROM my_table WHERE id = :id")
    LiveData<Content> getContentById(long id);
}

I can't understand what I am doing wrong. Can someone please help. Thanks!!

Edit: To clarify, this is how the code looks.

return new NetworkBoundResource<Content, CreateContent>(appExecutors) {
    @Override
    protected void saveCallResult(@NonNull CreateContent item) {
       //Something
    }

    @Override
    protected boolean shouldCall(@Nullable Content data) {
        //Something;
    }

    @Override
    protected LiveData<Content> createDbCall() {
        MediatorLiveData<Content> mediatorLiveData = new MediatorLiveData<>();
        appExecutors.diskIO().execute(() -> {
                    long id = contentDao.insert(content);
                    Log.i("LIVE", id + "");
                    LiveData<Content> content = contentDao.getContentById(id);

                    mediatorLiveData.addSource(content, new Observer<Content>() {
                        @Override
                        public void onChanged(@Nullable Content c) {
                            Log.i("LIVE", "FIRED");                                                
                            mediatorLiveData.removeSource(content);
                            mediatorLiveData.postValue(c);
                        }
                    });

            });
        return mediatorLiveData;
    }

    @NonNull
    @Override
    protected LiveData<ApiResponse<CreateContent>> createCall() {
        //Something
    }
}.asLiveData();

The value is returned to the constructor.

@MainThread
    public NetworkBoundResource(AppExecutors appExecutors) {
        this.appExecutors = appExecutors;
        result.setValue(Resource.loading(null));
        //TODO:: Add method to check if data should be saved. This should apply for search data.
        LiveData<ResultType> dbSource = createDbCall();
        result.addSource(dbSource, data -> {
            result.removeSource(dbSource);
            if (shouldCall(data)) {
                fetchFromNetwork(dbSource);
            } else {
                result.addSource(dbSource, newData -> setValue(Resource.success(newData)));
            }
        });
    }

Upvotes: 16

Views: 9627

Answers (2)

Reejesh PK
Reejesh PK

Reputation: 4150

In case anyone is re initializing a mediator live data, the old object only will be observed, new object will not be observed.

That is , dont do this:

  1. Observe myViewModel.observe(....)

  2. Trying to allocate new memory to mediator myMediatorObj = new MediatorLiveData<>(); //this can be the issue. Try removing if you have any lines like this.

//after this point,anything set to the object myMediatorObj will not be observed

In case you are trying to reset the data, pass in some data that signals null/empty/rest.

Upvotes: 0

Chris
Chris

Reputation: 2362

As discussed you need to make sure the mediatorLiveData has an active observer attached.

If you take a look at the addSource method it checks whether any active observers are attached before subscribing to the source.

https://github.com/aosp-mirror/platform_frameworks_support/blob/d79202da157cdd94c2d0c0b6ee57170a97d12c93/lifecycle/livedata/src/main/java/androidx/lifecycle/MediatorLiveData.java#L95

Upvotes: 35

Related Questions