Cześć,
piszę aplikację z wykorzystanie rooma.

Mój przypadek: mam recycler view i w adapterze potrzebuję zrobić kilka updatów na bazie. Obiekty do aktualizacji są w trzech DAO, więc nie mogę użyć adnotacji @Transaction w pojedyńczym DAO.
Chcę to zrobić wywołująć metodoę na instacji bazy db.runInTransaction(Runnable body) (tutaj przykład: https://stackoverflow.com/a/48187673)
W powyższej odpowiedzi na stacku użytkownik odpisał "Access all your daos here".

db.runInTransaction(new Runnable() {
                          @Override
                          public void run() {
                                firstRepository.update(object);
                                secondRepository.update(object2);
                                thirdRepository.delete(object3);
                            }
                        });

Jednak jeśli zrobię to tak jak w powyższym przykładzie to dostaję błąd: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.

Jeśli chodzi o moje repozytoria to operacje w nich robię poprzez AsyncTask tak by właśnie nie wykonywać operacji na głównym wątku. Jak włączę możliwość wykonywania operacji na bazie w głównym wątku to powyższy kod działa.

Pytanie pierwsze: Czy włączenie operacji na bazie na głównym wątku jest prawidłowe w tym przypadku? Będzie to dobre rozwiązanie?

Spróbowałem rozwiązać ten problem tak by nie zezwalać aplikacji robienia operacji na bazie na głównym wątku, sprawę rozwiązełem tak:

  • Stworzyłem kolejne Repository, które ma w sobie zmienne klasowe kilku dao, czyli np: FirstDao, SecondDao, ThirdDao
  • w tym repozytorium mam metodę klasową, która ma zrobić moje trzy operację na bazie nazywam ją w stylu: updateTwoObjectsAndDeleteThird(FirstObject firstObject, SecondObject secondObject, ThirdObject thirdObject, Context context)
  • korzystam z klasy pomocniczej MyTaskParams, konstruktor przyjmuje tu trzy obiekty, które będę aktulizował / kasował w bazie, ta klasa jest po to by obiekt przekazać do klasy AsyncTask, która wykona moje trzy operacje
  • w metodzie updateTwoObjectsAndDeleteThird wywołuję anonimową klasę UpdateTwoObjectsAndDeleteThirdAsyncTask, ta klasa rozszerza AsyncTask<MyTaskParams, Void, Void>
  • w klasie UpdateTwoObjectsAndDeleteThirdAsyncTask mam metodę doInBackground
@Override
        protected Void doInBackground(MyTaskParams... myTaskParams) {
            AppDatabase db = AppDatabase.getInstance(context);
            final FirstObject firstObject = myTaskParams[0].firstObject;
            final SecondObject secondObject = myTaskParams[0].secondObject;
            final ThirdObject thirdObject = myTaskParams[0].thirdObject;

            db.runInTransaction(new Runnable() {
                @Override
                public void run() {
                    firstDao.update(firstObject);
                    secondDao.update(secondObject);
                    thirdDao.delete(thirdObject);
                }
            });
            return null;
        }

Powyższy kod działa, nie muszę zezwalać bazie na robienie operacji na głównym wątku, czy moje rozwiązanie jest poprawne? Tak się powinno robić kilka operacji na różnych dao, jeśli operacje mają być w jednej transakcji? Zastanawiam się czy tworzenie takiej klasy repository która ma kilka dao jest poprawne.