15

I'm developing an Android application that is targeting API level 8 (2.2, Froyo). I'm using a ContentProvider and that's simple enough, and I'm using SimpleCursorAdapter to fill out my list view, but I noticed in the documentation for SimpleCursorAdapter that the flagless constructor is deprecated with the following note:

This constructor is deprecated. This option is discouraged, as it results in Cursor queries being performed on the application's UI thread and thus can cause poor responsiveness or even Application Not Responding errors. As an alternative, use LoaderManager with a CursorLoader.

Since I'm targeting API level 8, a LoaderManager isn't tied to an Activity. The FragmentActivity class in the compatibility package does this, but I'm not using Fragments.

My question is: how exactly should I be using LoaderManager/CursorLoader in an app targeting a pre-11 API level? Am I forced to transition to Fragments or should I just revert back to the deprecated SimpleCursorAdapter constructor (but make use of an AsyncTask to keep it UI thread friendly, which is what the CursorLoader is supposed to do)?

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
mkuech
  • 411
  • 1
  • 4
  • 13
  • 1
    Check out this blog post: [**Understanding the LoaderManager (part 2)**](http://www.androiddesignpatterns.com/2012/05/why-you-should-use-loadermanager.html) – Adrian Monk Aug 02 '12 at 15:27
  • Hello, where is it documented that a LoaderManager is tied to Fragments? It is simply for retrieving data from a DB. The model layer is always detached from the UI layer in any sophosticated software paradigm. – IgorGanapolsky Jan 02 '14 at 00:30
  • @IgorGanapolsky In the documentation for LoaderManager: `Interface associated with an Activity or Fragment for managing one or more Loader instances associated with it. This helps an application manage longer-running operations in conjunction with the Activity or Fragment lifecycle` ...and the only types of `Activity`s that are associated for older platforms are `FragmentActivity`s. – mkuech Feb 20 '14 at 18:45
  • Right, the user said: "Am I forced to transition to Fragments". The answer is NO. A regular Activity will work fine for these purposes. – IgorGanapolsky Feb 20 '14 at 20:03
  • 1
    @IgorGanapolsky Right, but only on the post-fragment APIs. You don't have to transition to `Fragment`s, but you do at least have to transition to an `Activity` that supports `Fragment`s (which is trivial). Not disagreeing, just making it more clear in case anybody is still supporting GB or earlier. – mkuech Mar 28 '14 at 13:09

1 Answers1

23

Edit:

I've written fairly extensively about the LoaderManager in this blog post. Check it out and let me know if its helpful! :)


Original post:

Definitely, definitely, definitely go with LoaderManager. The CursorLoader class offloads the work of loading data on a thread, and keeps the data persistent during short term activity refresh events, such as an orientation change. In addition to performing the initial query, the CursorLoader registers a ContentObserver with the dataset you requested and calls forceLoad() on itself when the data set changes, and is thus auto-updating. This is extremely convenient as you don't have to worry about performing queries yourself. Of course it is possible to make use of AsyncTask to keep your application UI thread friendly, but it will involve a lot more code... and implementing your class so that it will, for example, retain the loaded Cursor over Activity won't be simple. The bottom line is that LoaderManager/Loader will do this automatically for you, as well as taking care of correctly creating and closing the Cursor based on the Activity lifecycle.

To use LoaderManager/CursorLoader in an app targeting a pre-11 API level, simply use the FragmentActivity class in the compatibility package. A FragmentActivity is just an Activity and has been created for Android compatibility support, and does not require the use of Fragments in your application. Just use getSupportLoaderManager() instead of getLoaderManager() and you should be all set. You could, of course, implement a parent FragmentActivity for each screen and have it displays a its layout in a Fragment (by making use of FragmentActivity.getSupportFragmentManager() in the Activity's onCreate() method). This design might make the transition to multi-pane layouts easier if you ever decide to optimize your application for tablets. It's a nice learning experience too :).

This is a pretty nice tutorial too. Try and work your way through it and don't hesitate to leave a comment if you have any other questions.

Community
  • 1
  • 1
Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
  • **note that there is a [typo](http://mobile.tutsplus.com/tutorials/android/android-sdk_loading-data_cursorloader/comment-page-1/#comment-15832) in the tutorial i posted.** other than that, it's great! :) – Alex Lockwood Jan 17 '12 at 19:22
  • Hmmm, I attempted this, but my view was blank. I must have missed something else. But it's nice to have direction! Thanks! One question though, what exactly is the harm in using CursorLoader directly inside my Activity vs. using it inside of LoaderManager? Out of curiosity, would I be able to simply skip using LoaderManager and reap the same benefits (beyond having to manage my own cursor, that is)? – mkuech Jan 17 '12 at 20:06
  • 1
    There isn't any harm, but you lose all of the benefits of using LoaderManager. For bigger screens it becomes more important that you query on a separate thread since configuration changes involve recreating the entire view layout (and you don't want anything to block this operation on a tablet since layouts are often more complex). By any means you can implement your class to do this on a separate thread using AsyncTask as I mentioned before, but my point is that LoaderManager does this all for you (and manages the cursor too), so its very convenient and its pretty easy to get it working too. – Alex Lockwood Jan 17 '12 at 20:41
  • What specifically are you trying to set up that comes up blank? – Alex Lockwood Jan 17 '12 at 20:42
  • Thank you, that's very informative! To answer your question on the blank view, that was just a lapse of sanity regarding my test data (figures). It works perfectly fine now. This is definitely easier to implement for async queries! – mkuech Jan 17 '12 at 21:28
  • The tutorial assumes you have worked through [this tutorial](http://mobile.tutsplus.com/tutorials/android/android-compatibility-working-with-fragments/), which probably explains your confusion. – Alex Lockwood May 26 '12 at 19:37
  • The tutorial is very confusing in Step 3 where it says **changes to the onCreate() method**. It does not talk about FragmentActivity anywhere. @AlexLockwood I will not say it the best tutorial. It surly need an edit. But +1 for your answer. – Gaurav Agarwal May 26 '12 at 19:37
  • @AlexLockwood - Hey great suggestions. I followed your answer above and the tutorial you referenced. However, I am getting an IllegalArgumentException. I posted my code and question here. http://stackoverflow.com/questions/11803754/android-cursorloader-and-loadermanager-error If you happen to get some time to look at it and see something wrong, I would appreciate it. Thanks. – ControlAltDelete Aug 03 '12 at 21:52
  • @Alex Lockwood Is LoaderManager and CursorLoader still best practice these days for, say loading SQLite data into a RecyclerView? Do any of the newer methods like JobIntentService() or JobScheduler offer any major advantages? – AJW Oct 08 '18 at 15:00