问题
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 ?
回答1:
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
orRunnable
, the exception is not handled (in theCallable
case it is, but is rethrown). This means you need to handle it in the code calling eitherrunInTransaction(Callable)
orrunInTransaction(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 touserCheckedIn(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;
}
来源:https://stackoverflow.com/questions/58038053/returning-value-from-runintransaction-in-android-room-database