0

Currently I am displaying data from an SQLite database in a multiple-column ListView. However, I would like to use calculated columns in my data involving more complicated mathematical functions than those available in SQLite queries. In this thread the following advice was given for this sort of situation:

... if you are putting the Cursor into some sort of CursorAdapter, you could: (1) convert the Cursor into an ArrayList, where Position is some Java class you define with your data (2) close the Cursor, to release the RAM it takes up (3) sort the ArrayList using Arrays.sort() (4) wrap the ArrayList in an ArrayAdapter and use that where you had been using your CursorAdapter

My problem is that I get stuck at step (4), because ArrayAdapter seems to be less flexible than SimpleCursorAdapter. I have been using SimpleCursorAdapter to define the mapping from the database columns to the ListView, but there seems to be no equivalent method defined for an ArrayAdapter.

I have seen references on the web to an Android object called ArrayListCursor. This sounds as if it would do just what I want, but it does not appear in the current Android Reference and it doesn't seem to be recognised by Eclipse.

If ArrayListCursor has been superseded what has replaced it?

Community
  • 1
  • 1
prepbgg
  • 3,564
  • 10
  • 39
  • 51

1 Answers1

1

I do not remember ever seeing an ArrayListCursor. There is a MatrixCursor, which allows you to build up a Cursor from rows and cells. You can also implement AbstractCursor to do whatever you want.

Whatever you do, try to minimize the data copying you do, which is why I would recommend either:

  • Creating your own AbstractCursor subclass that wraps your database Cursor and blends in the calculated values
  • Just leave your original Cursor alone and use a CursorAdapter subclass to blend in your calculated values
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks very much for your prompt answer. For my limited skill level I don't think I can tackle your suggestions without a fully worked out example, and I've not been able to find one. Reading the Android reference for Cursor, which specifically says that a Cursor provides access to the results of a database query, made me think of a workaround: why not use my cursor to read my database query line-by-line and write the data to a temporary SQLite table along with the calculated columns, then define a new cursor based on a query that returns everything in the temporary table? – prepbgg Dec 20 '10 at 07:56
  • @prepbgg: What you are describing is more difficult to implement than are my suggestions above, and slower as well. Even the `MatrixCursor` option is better than that. – CommonsWare Dec 20 '10 at 08:01
  • Yes, but I know how to do what I describe. I recognise it would be inefficient but that's not a big issue in the particular context. I don't know how to "create an AbstractCursor subclass that wraps my database Cursor" or to "use a CursorAdapter subclass". However, I'm always keen to try to get to grips with new concepts. Can you point to any tutorials, please? – prepbgg Dec 20 '10 at 11:24
  • The tutorials at http://thinkandroid.wordpress.com/2010/01/09/simplecursoradapters-and-listviews/ and http://thinkandroid.wordpress.com/2010/01/11/custom-cursoradapters/ look as if they may show me how to proceed. I'll have a go! – prepbgg Dec 20 '10 at 11:42
  • No, I'm afraid http://thinkandroid.wordpress.com/2010/01/11/custom-cursoradapters/ has not helped me. He just seems to use the fields from the underlying database so the example doesn't show me how to modify the data or add new fields. Any other suggestions, please? – prepbgg Dec 20 '10 at 12:09
  • When I posted earlier in this thread I had no idea how slow Android is at inserting data into an SQLite table: after I had implemented this idea I found by watching the program's progress in LogCat that each call to SQLiteDatabase.insert() took around 750 milliseconds! So, I've recoded the prog so that it feeds the data from the database query cursor, along with calculated columns, into a MatrixCursor and feeds that into the SimpleCursorAdapter for the ListView. This takes 1 ms or less per row, so seems very satisfactory for my purpose. Thanks very much for the suggestion, CommonsWare! – prepbgg Dec 23 '10 at 13:42
  • @prepbgg: If you do not use your own transactions, each insert into a SQLite database is its own transaction. Each transaction writes to flash. Flash writes can be really slow. Hence, if you do a bunch of inserts, you probably want to wrap that in your own transaction, so they do a single flash write in toto, rather than one per insert. – CommonsWare Dec 23 '10 at 17:22
  • Thanks. I'll bear that in mind. (Changing the subject, I've just been trying to generalise my routine for copying data from a database query Cursor, along with calculated columns, into a MatrixCursor, so that the same routine will handle a variable number of columns of different types. I've been frustrated to find that although the Cursor class has getString, getDouble, etc, it doesn't seem to have either a getObject method or a getColumnDataType method. From googling it seems that other implementations of SQLite do provide these. I've managed to work around this but it limits my flexibility.) – prepbgg Dec 23 '10 at 21:38
  • Incidentally, I should have added (in case it helps anyone reading this thread) that I found the following thread gave useful help on MatrixCursor. (Note the important point that the MatrixCursor must have an "_id" column.) http://stackoverflow.com/questions/1882156/using-matrixcursor-and-simplecursoradapter-in-a-listview-with-text-and-images – prepbgg Dec 23 '10 at 21:43
  • @prepbgg: `MatrixCursor` does not need an `_id` column. However, *any* `Cursor` used with `CursorAdapter` (or subclasses like `SimpleCursorAdapter`) needs an `_id` column. – CommonsWare Dec 24 '10 at 07:27