I like to create Cursor-backed POJO classes. A Cursor-backed POJO class has a constructor that takes a Cursor and provides the following benefits:
- Easy to use getters that return the proper content type, much better
than getting indexes and having to remember the type of data in the
database
- Getter methods that compute their results from other getters, just like how OO programming ought to be
- Getter return values can be enums!
These few benefits are well worth some boilerplate code, many many bugs have been averted now that user-engineers aren't accessing cursor columns themselves. We still use the CursorAdapter class, but the first line in the bindView method is to create the Cursor-backed POJO from the Cursor and from then on the code is beautiful.
Below is an example implementation, it's a snap for user-engineers to turn an opaque cursor into clearly defined User object, from that point on it can be passed around and accessed just like a regular POJO so long as the backing cursor is not closed. The SmartUserCursor is a special class I wrote to ensure that the cursor position is remembered and restored before the cursor is accessed and it also stores the cursor column indexes so lookups are fast.
EXAMPLE:
public class User {
private final SmartUserCursor mCursor;
public User(SmartUserCursor cursor, int position) {
mCursor = new SmartUserCursor(cursor, position);
}
public long getUserId() {
return mCursor.getLong(SmartUserCursor.Columns.userId);
}
public UserType getType() {
return UserType.valueOf(mCursor.getString(SmartUserCursor.Columns.type));
}
public String getFirstName() {
return mCursor.getString(SmartUserCursor.Columns.firstName);
}
public String getLastName() {
return mCursor.getString(SmartUserCursor.Columns.lastName);
}
public final String getFullName() {
return getFirstName() + " " + getLastName();
}
public static User newUserFromAdapter(BaseAdapter adapter, int position) {
return new User((SmartUserCursor)adapter.getItem(position), position);
}
public static User newUserBlocking(Context context, long UserId) {
Cursor cursor = context.getContentResolver().query(
Users.CONTENT_URI_CLIENT,
Users.DEFAULT_USER_PROJECTION,
Users.Columns.USER_ID+"=?",
new String[] {String.valueOf(UserId)},
null
);
if (cursor == null || !cursor.moveToFirst()) {
throw new RuntimeException("No User with id " + UserId + " exists");
}
return new User(new SmartUserCursor(cursor, Users.DEFAULT_USER_PROJECTION), -1);
}
public final void closeBackingCursor() {
mCursor.close();
}
}