schematic icon indicating copy to clipboard operation
schematic copied to clipboard

Proposal: helper to retrieve column value from cursor

Open MyDogTom opened this issue 8 years ago • 3 comments

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 of getColumnIndex. 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.

MyDogTom avatar Dec 31 '15 12:12 MyDogTom

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.

SimonVT avatar Dec 31 '15 13:12 SimonVT

@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();

geovanisouza92 avatar Dec 31 '15 13:12 geovanisouza92

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.

SimonVT avatar Jan 02 '16 22:01 SimonVT