9

The app has data in a SQLite database. The UI is primarily a RecyclerView. The question is how to best to transfer data from the database into the UI, whilst keeping off the main thread?

I originally planned to use a CursorLoader, ContentProvider, and RecyclerView. But reading around it looks like RecyclerView has no out-of-the-box support for Cursor-supplied data. Dang.

That then leaves me with a few other options...

  1. AsyncTask to load the data, put it into model objects, and pass into the RecyclerView Adapter. Aside from being ugly, it isn't config-change friendly.

  2. A custom Loader that loads the data from SQL and pushes it into model objects.

  3. Use a Cursor loader, and when it returns the Cursor iterate through it to push the data into model objects. I suspect this would occur on the main thread and may damage performance.

  4. Use Otto to send a request message to request data, and then return a model objects collection by return message. There may be ~500 objects so I think I may rather abusing Otto doing this.

If I am using a collection of model objects instead of a Cursor I see less benefit to a ContentProvider, and I also lose the ability for the UI to auto-refresh on data changes (which may be useful).

None of these options appeal much, is there a better way? The app is under time pressure so whatever it is needs to be fairly quick to implement. Unfortunately the UI needs to scroll horizontally and only targets Lollipop, so RecyclerView does seem a better bet than ListView.

Ollie C
  • 28,313
  • 34
  • 134
  • 217
  • I use method 3 in one of my apps and in the onLoadFinished I spawn a new thread the create the model objects from the data. I have not had a problem with this method yet – tyczj Jan 28 '15 at 14:46
  • 1
    See https://gist.github.com/Shywim/127f207e7248fe48400b and please dont iterate over the cursor, it has little sense and as you said it degrades the performance – pskink Jan 28 '15 at 14:49
  • Wouldn't you be able to take the cursor and shove it into a different task? Still not desirable of course. – G_V Jan 28 '15 at 15:51
  • @G_V the problem with that though is the cursor could be closed by the loader before you are done looping it – tyczj Jan 28 '15 at 17:01
  • @pskink Your response and the pointer to the Adapter code has got my project code working well - it's simple code, easy to read, off the main thread, and the UI is very smooth. Feel free to post your comment as an answer and I will accept it. – Ollie C Jan 29 '15 at 09:42
  • @tyczj why whould the CursorLoader close it? – pskink Jan 29 '15 at 10:03
  • @pskink because the loader manager handles closing the cursor and if a new cursor comes while you are already parsing the old cursor it gets closed because it is no longer valid. see this question http://stackoverflow.com/questions/10957252/using-a-cursor-returned-from-a-loadermanager-in-an-asynctask – tyczj Jan 29 '15 at 14:24
  • @tyczj this is the point " if a new cursor comes", it means when underlying data changes the new Cursor is requested - it is the main purpose of CursorLoader to deliver up-to-date data, if the underlying data doesn't change you can keep the Cursor for a week or two, it won't be closed - this is how CursorAdapter uses the Cursor, it doesn't "copy" the content of the Cursor to show the data – pskink Jan 29 '15 at 17:55
  • @pskink i know I was just pointing out that bit of information to G_V as to why you dont really want to hand it off on to another thread – tyczj Jan 29 '15 at 17:58

1 Answers1

6

use this simple adapter https://gist.github.com/Shywim/127f207e7248fe48400b, alternatively you could use android.support.v17.leanback.widget.ItemBridgeAdapter with android.support.v17.leanback.widget.CursorObjectAdapter but why to make own life harder?

pskink
  • 23,874
  • 6
  • 66
  • 77