I am currently using Android Room to store some small data on Android. In theory I should have no problem using allowMainThreadQueries() since all of my data is small, but in order to future-proof my program I am trying to move all of my calls into a separate thread. As of right now I have a static Handler in AppConfig a class that is initialized on the app's initial launch and is visible app wide:
HandlerThread thread = new HandlerThread("dbHandlerThread");
thread.start();
serviceHandler = new DbHandler(thread.getLooper(),lApp.getBaseContext(),dbName);
DbHandler is a custom class that extends Handler and has the following constructor:
DbHandler(Looper looper, Context context, String dbName) {
super(looper);
AppDatabase db = Room.databaseBuilder(context, AppDatabase.class, dbName)
.fallbackToDestructiveMigration().build();
coDao = db.countOrderDao();
plDao = db.productListDao();
pDao = db.productDao();
}
It overrides handleMessage(Message msg) and depending on the msg.what performs a variety of insert/update/delete operations all of which are void.
In the UI thread in some Activity I call this code:
Message msg = Message.obtain();
msg.what = AppConfig.SAVE;
//insert some data and args
AppConfig.serviceHandler.dispatchMessage(msg);
My understanding is that since the Handler is running on a new thread/looper and since the UI thread is not waiting for any output there should not be any problem with this. However, anytime I call this code I get the same error as if I was accessing the database directly in the ui thread:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
What am I doing wrong?
I found the error:
dispatchMessage(msg) overrides any threads and manually calls the handleMessage method, while send message respects the looper/thread for the handler.
Solution:
Replace dispatchMessage(msg) with sendMessage(msg)