Search code examples
androidrealm

Close Realm instance after execution finishes


I want to close my Realm instance in executeTransactionAsync after execution finished. Reason is that my applications main thread keeps on freezing, I think the reason for it is that the background realm instance is not being closed after execution finishes. See my code below:

realm.executeTransactionAsync(new Realm.Transaction() {
                    @Override
                    public void execute(Realm realm) {
                        // Execute realm code
                        realm.copyToRealmOrUpdate(myData);
                        // Can I close the realm instance here without getting an 
                        // error? realm.close(); causes an error.
                    }
                }, new Realm.Transaction.OnSuccess() {
                    @Override
                    public void onSuccess() {
                        Log.i("CB", "success");
                        // looks like I cannot access the execute Realm 
                        // instance here.
                        // Closing realm.getDefaultInstance does not change my issue
                    }
                }, new Realm.Transaction.OnError() {
                    @Override
                    public void onError(Throwable error) {
                        Log.i("CB", "error - " + error.getMessage());
                    }
                });
            }

Please see my comments. My application screen just turns black. Execution completes successfully and onSuccess() gets called, but I cannot access the execute realm instance to close it from here.

Do you have any suggestions as to what I can try? Am I doing something wrong?

Thank you in advance.

EDIT

07-19 11:43:42.379 8146-8146/com.shortterminsurance.shortterm I/CB: success
07-19 11:43:43.258 8146-8152/com.shortterminsurance.shortterm W/art: Suspending all threads took: 33.234ms
07-19 11:43:43.266 8146-8156/com.shortterminsurance.shortterm I/art: Background partial concurrent mark sweep GC freed 476307(17MB) AllocSpace objects, 512(10MB) LOS objects, 40% free, 33MB/55MB, paused 7.261ms total 163.497ms
07-19 11:43:44.131 8146-8156/com.shortterminsurance.shortterm I/art: Background sticky concurrent mark sweep GC freed 408160(9MB) AllocSpace objects, 459(15MB) LOS objects, 35% free, 35MB/55MB, paused 10.287ms total 147.823ms
07-19 11:43:44.834 8146-8152/com.shortterminsurance.shortterm W/art: Suspending all threads took: 103.676ms
07-19 11:43:44.848 8146-8156/com.shortterminsurance.shortterm W/art: Suspending all threads took: 13.424ms

This is my logcat after my onSuccess gets called. I think the background instance of realm in execute keeps running for some reason :(.


Solution

  • The realm instance that is passed here

    @Override
    public void execute(Realm realm) {
    

    is closed for you. You don't have to worry about closing it yourself.

    If you check the source code for Realm.executeTransactionAsync(), you can find

    bgRealm.beginTransaction();
    try {
        transaction.execute(bgRealm);
    
        if (!Thread.currentThread().isInterrupted()) {
            bgRealm.commitTransaction(false, new Runnable() {
                @Override
                public void run() {
                    // The bgRealm needs to be closed before post event to caller's handler to avoid
                    // concurrency problem. eg.: User wants to delete Realm in the callbacks.
                    // This will close Realm before sending REALM_CHANGED.
                    bgRealm.close();
                }
            });
            transactionCommitted = true;
        }
    }
    ...
    

    So first it calls .execute() on your transaction, and after that it closed the realm instance it passed to you.