schematic
schematic copied to clipboard
Proposal: helper to retrieve column value from cursor
Hi, @SimonVT . I'm thinking about creating merge request with "column getter" functionality (see description below). Please tell me if it suitable for library or not.
Motivation: Instead of writing String note = cursor.getString(cursor.getColumnIndex(NoteColumns.NOTE));
just call String note = NotesGetter.noteString(cursor);
. It's more significant when you deal with nullable columns.
Couple details about suggested implementation:
- Use
getColumnIndexOrThrow
instead ofgetColumnIndex
. I think this approach is more robust because let identify problems earlier. - Create implementation for all primitive types and for wrappers. Support
null
for wrappers. Example of generated code.
public static Integer getIdIntOrNull(Cursor cursor) {
int index = cursor.getColumnIndexOrThrow(NoteColumns.ID);
if (cursor.isNull(index)) {
return null;
} else {
return cursor.getInt(index);
}
}
public int getIdInt(Cursor cursor) {
return cursor.getInt(cursor.getColumnIndexOrThrow(NoteColumns.ID));
}
- I'll always generate
null
support despite@NotNull
annotation. - I'm still looking for better class and method names.
I've been meaning to add something like this. Could be changed to use getColumnIndexOrThrow
as well as adding get(Type)OrNull
methods.
I'm not sure it's worth generating getters for each table compared to what you gain over a simple helper class.
@MyDogTom I use a similar approach, but mine's just a helper class:
package ...;
import android.database.Cursor;
import android.support.annotation.Nullable;
import java.util.Date;
public abstract class CursorHelper {
public static long getLong(Cursor cursor, String columnName) {
int columnIndex = cursor.getColumnIndex(columnName);
if (columnIndex >= 0 && !cursor.isNull(columnIndex)) {
return cursor.getLong(columnIndex);
}
return 0;
}
public static int getInt(Cursor cursor, String columnName) {
int columnIndex = cursor.getColumnIndex(columnName);
if (columnIndex >= 0 && !cursor.isNull(columnIndex)) {
return cursor.getInt(columnIndex);
}
return 0;
}
@Nullable
public static Date getDate(Cursor cursor, String columnName) {
long since = getLong(cursor, columnName);
if (since > 0) {
return new Date(since);
}
return null;
}
@Nullable
public static String getString(Cursor cursor, String columnName) {
int columnIndex = cursor.getColumnIndex(columnName);
if (columnIndex >= 0 && !cursor.isNull(columnIndex)) {
return cursor.getString(columnIndex);
}
return null;
}
private CursorHelper() {
}
}
Then I just copy and paste this class for each project. Sometimes I extend it with more methods. And then, I call like this:
final Date createdAt = CursorHelper.getDate(cursor, ActionColumns.CREATED_AT);
final String action = CursorHelper.getString(cursor, ActionColumns.ACTION);
As schematic generates a class to populate ContentValues
(named as {@Database.className()}Values
) I think that could be useful to have one to get cursor values too, something like:
final {@Database.className()}Cursors cursors = new {@Database.className()}Cursors();
final {Model Name}Cursor modelCursor = cursors.for{Model Name}(cursor);
modelCursor.createdAt();
modelCursor.action();
modelCursor.id();
Added the helper class in e020ecb at least. I think having idLong()
, idInt()
, etc, methods is kind of ugly, and I don't really want to make the @DataType
any more specific.
Will keep it open in case someone comes up with an awesome solution.