Search code examples
javaandroidrealm

executeTransactionAsync doesn't refresh data after onSuccess call


First, previous answers to similar questions on SO didn't helped me at all.

Sometimes when calling executeTransactionAsync() I don't get refreshed data on UI thread in onSuccess method.

For example, in the following snippet I have a part of the callback instance that should store received data to Realm. This callback instance is created in the UI thread (of course):

@Override
public void onResponse(final Response<TicketAddItemResult> response, Retrofit retrofit) {
    if (!isSuccess()) {
        return;
    }
    Realm realm = Realm.getDefaultInstance();
    if (realm.isClosed()) return;

    try {
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                RealmTicketsHandler.updateCurrentTicket(realm, response.body().result);
                //!!!! Underneath log sometimes from here shows different result than the log in onSuccess with the same query
                Log.d(TAG, "execute: (thread) size = " + RealmTicketsHandler.getCurrentTicket(realm).getTicketItems().size() );
            }
        }, new Realm.Transaction.OnSuccess() {
            @Override
            public void onSuccess() {
                Realm realm = Realm.getDefaultInstance();
                try {
                    Log.d(TAG, "execute: (onSuccess) size = " + RealmTicketsHandler.getCurrentTicket(realm).getTicketItems().size() );
                } finally {
                    realm.close();
                }
                postEvent(new TicketRefreshed());
            }
        });
    } finally {
        realm.close();
    }
}

In the method RealmTicketsHandler.updateCurrentTicket(realm, data) I just get object (Ticket) from realm, create new object (TicketItem) which will be added to RealmList<TicketItem> and that's it.

Nevertheless, after updating Realm in background thread, log from execute() method of Realm.Transaction object shows me that everything is added correctly, but in the OnSuccess() method of Realm.Transaction.OnSuccess instance, log sometimes doesn't show expected result.

Object of TicketItem doesn't have any references to Ticket.

Could someone explain me why is this happening?

Realm version: 4.2.0, but the same behaviour can be experienced in 4.1.1

NOTE: opening Realm in onSuccess is done just to directly show if the data is refreshed in the current thread.

NOTE 2: I also have some background threads without loopers that use realm, but they act as they should and data is quickly refreshed on the UI thread.


Solution

  • This should be an expected behavior, onSuccess() will guarantee two things:

    1. The transaction has been executed.
    2. The data was changed in the transaction has been included in the current DB version on the thread where the asycn transaction started when the onSuccess() is called.

    The below case may help you to understand why you see different logs in the transaction block and onSuccess().

    1. UI thread calls executeTransactionAsync() to change the data to version 1.
    2. The background thread executes the transaction, and now the DB on the background thread has data version 1.
    3. Another thread executes a transaction and changes the data to version 2.
    4. The UI thread received the DB update event and gets the data changes both in step 2 and 3. onSuccess() is called, and you are not only seeing the changes in step 2, but also together with data changes in step 3. So you may see the data version 3 in the onSuccess() callback.

    Be noticed that, onSuccess() only guarantees that you will have the data changed in the async transaction, but it won't and cannot (well, due to concurrency is hard to guarantee this) guarantee you only see the data changes in the corresponding async transaction. The data changed later could also be seen in the onSuccess().