Must an activity or fragment have a separate loader for type of each database operation performed?
Question
Seems the Google-recommended way (using the android support library) for a fragment or activity to interact with a sqlite database is via a loader that extends AsyncTaskLoader and works similar to the way CursorLoader does for ContentProviders.
A single activity or fragment may interact with a database in a variety of ways, updating, deleting, and querying data in one or more tables. But since a loader has only one place in which to carry out database manipulation (i.e. in loadInBackground()
), is the developer expected to write a separate loader for each type of interaction, especially since it seems the only way to parametrize the behavior in loadInBackground()
is by passing arguments to the loader's constructor via the args
argument to LoaderManager.initLoader()
?
Thanks much.
Solution
When not using a ContentProvider
, i.e. when using sqlite directly, use AsyncTaskLoader
if the set of database operations to be performed returns a Cursor
. The set may include any kind of operation - update, query, delete, insert. These operations should be executed in AsyncTaskLoader.loadInBackground()
.
If the set of database operations does not result in a Cursor
being returned, use an AsyncTask
. In this case, the operations should be executed in AsyncTask.doInBackground()
.
OTHER TIPS
There are two key benefits to using a CursorLoader
in your app over Activity.managedQuery():
- The query is handled on a background thread for you (courtesy of being build on
AsyncTaskLoader)
so large data queries do not block the UI. This is something the docs recommended you do for yourself when using a plainCursor
, but now it's done under the hood. CursorLoader
is auto-updating. In addition to performing the initial query, the CursorLoader registers aContentObserver
with the dataset you requested and callsforceLoad()
on itself when the data set changes. This results in you gettingasync
callbacks anytime the data changes in order to update the view.
Each Loader instance is also handled through the singular LoaderManager
, so you still don't have to manage the cursor directly, and now the connection can persist even beyond a single Activity. LoaderManager.initLoader()
and LoaderManager.restartLoader()
allow you to reconnect with an existing Loader already set up for your query and, in some cases, instantly get the latest data if it is available.
Your Activity or Fragment will likely now implement the LoaderManager
.Callback interface. Calling initLoader()
will result in the onCreateLoader() method where you will construct the query and a new CursorLoader
instance, if necessary. The onLoadFinished()
method will be fired each time new data is available, and will include the latest Cursor for you to attach to the view or otherwise iterate through.
In addition, there is a pretty good example of all this fitting together on the LoaderManager
class documentation page: http://developer.android.com/reference/android/app/LoaderManager.html
Hope that Helps!
Based on the previous answers, I'm not sure if this is what you're asking exactly. But YES, you have to make a loader with its unique id for each data set i.e. each type of query you perform.