4

Iam trying to figure out what RunInTransaction eventually does. Room documentation doesnt say much other than "Executes the specified Runnable in a database transaction".

From what i understand:

If we have an asynchronous operation like a query and then some insertion without the runInTransaction

roomDB.runInTransaction(new Runnable() {
    @Override
    public void run() {
          query
    }
});

 insertions
 insertions

The runInTransaction locks the database until the specified operation is completed. So at the first insertion the Thread pauses (please correct me) until the runInTransaction completes.

How can i control which procedure executes first?

But i think that database either way locks the tables and without using runInTransaction method. Please correct me if iam wrong.

Updated

 @Dao
 public interface RepoDao {

    @Query("SELECT * FROM Table")
    LiveData<List<Table>> getAll();

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insert(List<Table> table);
}

Main Activity

repo = ((BasicApp)getApplication()).getRepository();

repo.insertDataFromNetwork();

((BasicApp)getApplication()).getDatabase().repoMethods()
.getAll().observe(this, new Observer<List<Table>>() {
        @Override
        public void onChanged(@Nullable List<Table> message) {
            Log.d("hello");

        }
    });;

insertDataFromNetwork

mDatabase.runInTransaction(new Runnable() {
                   @Override
                   public void run() {

                           mDatabase.repoMethods().insert(....);
                           mDatabase.repoMethods().insert(....);
                           mDatabase.repoMethods().insert(....);
                           mDatabase.repoMethods().insert(....);
                           mDatabase.repoMethods().insert(....);

                       }
                   }
               });
Nick
  • 2,818
  • 5
  • 42
  • 60

1 Answers1

4

A transaction symbolizes a unit of work performed within a database management system against a database. (Wikipedia)

It means that, if you, for example, will insert 10 users and update 10 other users not using runInTransaction method, Room will execute each insertion and update as a single action (transaction), and will update observers, who are observing changes on the Users table each time. While doing the same thing in runInTransaction method will perform all this changes as one action (transaction) and will notify listeners only once.

How can i control which procedure executes first?

Just run them sequentially in a single thread. And don't run database transactions in the main thread.

Demigod
  • 5,073
  • 3
  • 31
  • 49
  • if i run asynchronous operations with synchronous operations sequentially there will be problems. see https://stackoverflow.com/questions/44711911/android-room-database-transactions – Nick Jun 07 '18 at 08:54
  • That's because no one runs two operations asynchronously if the second should be done after first. Use proper mechanism for this - wait for first to finish, and then run second. Or run them synchronously in a single thread. – Demigod Jun 07 '18 at 09:41
  • I just did 10 insertions to one table that has live data in a runInTransaction and the observer notified 10 times and not only one – Nick Jun 07 '18 at 17:01
  • Should be notified only once, how you did the test? (possible? https://stackoverflow.com/questions/49426306/livedata-observer-is-triggered-during-runintransaction-in-room-database) – Demigod Jun 08 '18 at 07:54
  • See in the updated section.5 insertions and only trigger 2 logs with or without the runInTransaction method because only the last 2 make it to the observer – Nick Jun 08 '18 at 08:09