Search code examples
androiddatabaseandroid-roomcallable

Returning value from runInTransaction() In Android Room database


There is not much documentation to understand how exactly does runInTransaction() method works. While executing multiple operations on different DAO's if no value is to be returned I could use runInTransaction(Runnable body) OR runInTransaction(Callable<V> body) if any result is to be returned.

Query that I have: If all the queries in the transaction are successful, then I want to return an image object that needs to be uploaded to a server on successful transaction If any exception occurred or the transaction was not successful I need to return a boolean with false to indicate the user that some error occurred.

Here is the method:

public boolean userCheckedIn(final User user) {
    try {
        appDatabase.runInTransaction(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                if (user != null) {

                   //Add entry in table A
                     appDatabase.UserDao().add(user);

                   //Update entry in table B 

                   //Delete an entry from table C 

                    Event image = updateUserAction(action);
                    return image;
                }
                return null;
            }
        });

    } catch (Exception e) {
        return false;
    }
    return true;
}

In the above method, what I intend to do is, if all the database executions are a success I need to return an image which will be uploaded to the server. If there is any exception that occurred or any error occurred while doing the db transaction I need to return false to let user know an error occurred. Not sure if I got it right. Also, should I be putting the runInTransaction in try catch block ?


Solution

  • The code for runInTransaction(Callable) is equivalent to the runInTransaction(Runnable) version:

    • if the transaction succeeds (this is, no exceptions are thrown) it sets the transaction as successful (by calling setTransactionSuccessful(), without this is considered failed and will be rolled back).
    • ends the transaction in any case (at this point, if it was set as successful the whole transaction is committed, else is rolled back).
    • if an exception is thrown inside the Callable or Runnable, the exception is not handled (in the Callable case it is, but is rethrown). This means you need to handle it in the code calling either runInTransaction(Callable) or runInTransaction(Runnable).

    The main functional difference is that runInTransaction(Callable) returns the value returned by the Callable.

    So, your code can do two things:

    • either return the image on success or null on failure, and upload the image in the method calling to userCheckedIn(User) or,
    • upload the image inside your userCheckedIn(User) method

    The second solution (easier for me to show you the code given I don't have the code for the method calling to userCheckedIn(User)) will look similar to this:

    public boolean userCheckedIn(final User user) {
        try {
            Event image = appDatabase.runInTransaction(new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    if (user != null) {
                        //Add entry in table A
                        appDatabase.UserDao().add(user);
    
                        //Update entry in table B 
    
                        //Delete an entry from table C 
    
                        Event image = updateUserAction(action);
                        return image;
                    }
                    return null;
                }
            });
            if (image != null) {
                // Upload the image to the server
            } else {
                // No image available (probably because of the "if (user != null)"
                // inside Callable). I assume you want to return false in this case.
                return false;
            }
    
        } catch (Exception e) {
            return false;
        }
        return true;
    }