A History of Threading Mistakes

In Android app development, we are constantly having to fight to keep disk I/O off of the main application thread. Every millisecond that our code executes on the main application thread is a millisecond that the main application thread is not updating our UI. Our objective is to move as much disk I/O as possible off the main application thread. That is why we use all those nice reactive solutions from the preceding chapter.

The problem is that the nice encapsulation that we get from object-oriented programming also encapsulates knowledge of whether disk I/O will be done when we call a particular method.

Classic use of SQLiteDatabase encounters this with the rawQuery()/query() family of methods. They return a Cursor. You might think — reasonably — that those methods execute the SQL query that you request. In truth, they do not. All they do is create a SQLiteCursor instance that holds onto the query and the SQLiteDatabase. Later, when you call a method that requires the actual query result (e.g., getCount(), to get the number of returned rows), then the query is executed against the database. As a result, all the work that you do to call rawQuery() or query() on a background thread gets wasted if you do not also do something to force the query to be executed on that same background thread. Otherwise, you may wind up with the query being executed on the main application thread, with impacts on the UI.

greenDAO relations can work the same way. If you retrieve your Thingy on a background thread, then call getOtherThingy() on the main application thread, depending on what else has all occurred, getOtherThingy() might need to perform a database query… which you do not want on the main application thread.

Prev Table of Contents Next

This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.