Android - SQLite ContentResolver insert/delete/update on UI Thread?
Asked Answered
A

3

10

I have looked through many examples/tutorials of using SQLite in Android. Let's say you have an app that uses SQLite, ContentProvider, CursorLoader, a custom CursorAdapter. Now all major examples of this that I've found rely on a CursorLoader to fetch data to the CursorAdapter, which by the nature of CursorLoader happens in an Async - UI thread safe manner. However, these same examples all make insert/delete/update calls through the ContentResolver on the main thread (e.g. from onClick, onResume, onPause). (Example) They don't wrap these calls in an AsyncTask or launch a separate thread or use the AsyncQueryHandler. Why is this, how can so many well written blogs/examples make such an obvious mistake? Or are simple single row insert/delete/update calls so quick that they are safe enough to launch from the Main/UI thread? What is the proper way to do these quick calls?

Arcturus answered 27/10, 2014 at 9:34 Comment(1)
your last sentence is probably right: query operation is for sure much more complex than single insert/update/deletePoultice
D
5

I also got confused about the samples making calls on the main thread. I guess the samples just simplified the demonstrations avoiding extra threads and callbacks, since single insert/update/delete call may return quickly.

Besides the Loader pattern for query, android did provide a helper class AsyncQueryHandler, since API level 1, for async CRUD operations with full CRUD callbacks supported. The AsyncQueryHandler works inside with a HandlerThread for the async operations and delivers the results back to the main thread.

So I do believe the ContentProvider queries should run in worker threads other than the UI, and those samples may not be best practices according to the official design.

=== edit

Found an annotation from the official framework docs, see this or this, Line 255:

In practice, this should be done in an asynchronous thread instead of
on the main thread. For more discussion, see Loaders. If you are not
just reading data but modifying it, see {@link android.content.AsyncQueryHandler}.

=== edit 2 Link to actual android dev guide containing the above quote

Drabbet answered 7/4, 2015 at 6:8 Comment(4)
Right, I mentioned the AsyncQueryHandler in my question as well... it's still not very convincing that ALL of the tutorials and examples, that I've come across do this, just because its simpler and don't even mention that this is not how you should do it. For a proper answer I'd like either something official from Google (team member, doc, tutorial) or something along those lines (maybe a link to a respectable GitHub project that does this one way or another) that makes these light calls on the Main Thread, or uses something like AsyncQueryHandler...Arcturus
Otherwise everything else is just our opinion on this... :)Arcturus
@LeoK Got an offical doc that mentioned this. Please see my edits.Drabbet
Cool thanks, indirect, but essentially confirms what I wanted to know. Thanks. (P.S. I added a link to the actual doc)Arcturus
H
2

This question has been on my mind since a long time. I guess, this depends on the complexity of the file we are trying to Insert, Update or Delete. If our application is going to Insert or Update large files, it would be always right to do it asynchronously and if the files aren't going to be that big, running it on UI thread can be done.

However, it is always recommended to continue with Database operations on a separate thread.

Homes answered 27/10, 2014 at 9:46 Comment(1)
Thanks for the reply. This doesn't really fully explain why Tutorials that explain best practices and in other facets do things properly/safely in the case of insert/delete/update never bother with separate threads. Obviously I haven't read all the good tutorials out there so some good counter examples would be welcome. (Especially ones from Google or other reputable sources)Arcturus
A
0

I think you've answered your own question. I do believe CursorLoader extends AsyncTaskLoader. Calls made from UI thread only process the call TO the CusorLoader (which uses AsyncTask.) What is being done BY the call still does not occur on UI Thread. Making a call to a method/function that then runs things on a seperate thread is still doing work away from UI thread.

What work do you think is happening on the UI thread?

Please show Debug log if possible or example where you think work is done on UI. It shouldn't be.

Not trying to argue just want to know how you've come to the conclusion of UI work?

Appaloosa answered 21/11, 2014 at 4:2 Comment(1)
You're right about the cursor loader being async. This is what I wrote myself in the question. However, insert/delete/update calls are made through the ContentReslover not CursorLoader. Everything going through ContentReslover is done on the UI thread, if the call to it is made on the UI thread. This is easy to verify simply by adding a Thread.sleep(5000) to the beginning of insert override of your ContentProvider. If you do so you'll see your UI freeze for 5 seconds...Arcturus

© 2022 - 2024 — McMap. All rights reserved.