yahoo / squidb

SquiDB is a SQLite database library for Android and iOS
https://github.com/yahoo/squidb/wiki
Apache License 2.0
1.31k stars 132 forks source link

Consuming content provider query result using Squidb #200

Closed lpellegr closed 8 years ago

lpellegr commented 8 years ago

I have created a content provider for my app A by using Squidb 3.1.0. It follows the great explanations from the Wiki. The overriden query method from my content provider returns a Cursor to comply with the Android interface. It is done by casting the concrete object instance as follows:

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Query query;
        switch (URI_MATCHER.match(uri)) {
            case XXX:
                query = buildXXXQuery(); // make use of PROJECTION_MAP
                break;
            default:
                throw new UnsupportedOperationException("Unsupported URI: " + uri);
        }

        query.limit(getLimit(uri));
        SquidCursor<AbstractModel> cursor = mDatabase.query(AbstractModel.class, query);
        return (Cursor) cursor.getCursor();
}

Then, from another app B (which embeds the same data model as the one exposing the content provider), I would like to query the content provider of app A and iterate over the result using a SquidCursor. There is no problem to retrieve the result from the content provider:

CursorLoader cursorLoader = 
    new CursorLoader(getApplicationContext(), contentUri, null, null, null, null);

Cursor cursor = cursorLoader.loadInBackground();

but to do something like the following, it seems that cursor needs to be of type SquidCursor:

AndroidTableModel tableModel = new XXX();
while (cursor.moveToNext()) {
    tableModel.readPropertiesFromCursor(cursor.);
    Timber.d("DB entry %d loaded", tableModel.getRowId());
}

Unfortunately, the resulting cursor object cannot be casted to SquidCursor. Its type seems to be android.content.ContentResolver$CursorWrapperInner.

Is there a mean to achieve what I am trying to do? otherwise, what is the recommended way to handle content provider query result?

sbosley commented 8 years ago

I think the best answer to your question is that the constructor to SquidCursor is public, so you can build a SquidCursor yourself if you have all the necessary information. The three things you need are:

  1. An instance of ICursor. This can be constructed by calling new SquidCursorWrapper(cursor) on your ContentProvider cursor result.
  2. An optional model "hint" class. This would be for the type argument of the SquidCursor, or null if you don't care about the type argument.
  3. A list of Property objects corresponding exactly to the fields present in the cursor. Generally you'd want to get these from the model that backs the query for the particular URI, so it might be worth exposing these fields as part of your ContentProvider's contract.

When put together, it might look something like this:

Cursor contentProviderResult = ...;
SquidCursor<MyModel> squidCursorResult = new SquidCursor(
    new SquidCursorWrapper(contentProviderResult), 
        MyContract.MODEL_CLASS, MyContract.MODEL_PROPERTIES);

Then you can use the SquidCursor as usual.

Hope that helps!

lpellegr commented 8 years ago

@sbosley Thank you a lot for the explanations. My usecase is working.