Android: Extending CursorAdapter for custom ListView

Since I am just getting started with Android, I keep running into beginner’s troubles and misunderstandings. There is the really good documentation. But even so, some mistakes happen along the way.

One of these problems occurred when after finishing the Notepad tutorial I wanted to use my newly acquired knowledge to incorporate a ListView into my first project.

I am programming a tiny weight and BMI tracker and needed to track dates for my measurements of course (productivity hint: even if all your app will ever do, is to store ‘measures’: do not call your packages, variables and directories ‘measure’! It is prone to typos!).

[sourcecode language=”sql”]CREATE TABLE measures (_id integer primary key autoincrement,
weight real not null, measure_date datetime default current_timestamp)[/sourcecode]

Now sqlite – the android in-house database – does not support date types natively like mysql for example. So when retrieving my data for display with the SimpleCursorAdapter, I got the wonderful long that was stored in the database which is not very human readable.

Of course it is easy to use a long value that represents a timestamp to get a nice Date object, that can be formatted into pretty things:

[sourcecode language=”java” wraplines=”false”]private static final SimpleDateFormat DATEFORMAT = new SimpleDateFormat(‘HH:mm, dd/MM’);
private String formatDateFromString(String strDate) {
final long timestamp = Long.parseLong(strDate);
final String date = DATEFORMAT.format(new Date(timestamp));
return date;
}
[/sourcecode]

Yet all my google mojo failed and I could not find a solution how I would be able to call this function before it was put on screen. It took me far longer than it should have. My aversion to inheritance got in the way. But Frameworks are made for inheritance, duh!

 

I started trying to extend SimpleCursorAdapter. Fail. I managed to only spend 1 minute doing that and finally settled on extending CursorAdapter, which has two nice methods you must override to get what you want on the screen. Here are the relevant parts of the methods:

[sourcecode language=”java” wraplines=”false”]@Override
public void bindView(View view, Context context, Cursor cursor) {

final String date = cursor.getString(cursor.getColumnIndex(MeasureDbAdapter.KEY_DATE));
final TextView t = (TextView) view.findViewById(R.id.date);
t.setText(formatDateFromString(date));

}

@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final View view = LayoutInflater.from(context).inflate(R.layout.someViewId, parent, false);
return view;
}
[/sourcecode]

Voilà. Custom view, just like I wanted.

 

This entry was posted in android. Bookmark the permalink.

14 Responses to Android: Extending CursorAdapter for custom ListView

  1. Andi says:

    Most helpful, much appreciated!

  2. Dan says:

    Nice one; saved me a bunch of time and worked like a charm.

  3. Stinker says:

    Am I seeing something wrong, or do the same method ‘formatDateFromString’ in the example has one parameter and then two?

  4. Sascha says:

    Thx alot…you made my day

  5. Aman says:

    Hi Sonia,
    Very insightful, was looking for a solution to my problem and then found your article.
    I have an app where i am pulling calls from CallLog and displaying using a cursor adapter as you did because i need to format the date, which is not possible using SimpleCursorAdapter. I am new to Android so prone to silly mistakes. 🙂
    I need to know how you are calling this cursorAdapter in your Activity. I am using this code.
    startManagingCursor(calls);
    adapter = new MissedCallsAdapter(this, calls);
    setContentView(R.layout.scratch_layout);
    setListAdapter(adapter);
    But my app crashes before it starts. 🙁

  6. Aman says:

    Thanks Sonja.
    I was making a silly mistake of initialising the variables in the Adapter constructor method.
    Its working now. 🙂

  7. veysel says:

    Very Helpfull , thanks

  8. silver_man says:

    A million thank yous!!!