Android DBFlow and CursorLoader

2020-08-01 08:15发布

问题:

Anyone knows how to use cursorLoader with DBFlow ? I seen this issue but this is not added to DBFlow.

Thanks.

回答1:

You can find official docs here or you can implement it the way i have

DBFlow ver used 3

//I have edited my answer & provided easier way for content provider part below

add this to manifest inside application

<provider
        android:authorities="com.hashx19.pristinekashmir.mycontentprovider"
        android:exported="false"
        android:name=".MyContentProvider"/>

Create java file named MyContentProvider & copy below code in it & replace AUTHORITY ,ENDPOINT, AppDatabase(Your database name) ,TableClassName as per you project.

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.CursorIndexOutOfBoundsException;
import android.net.Uri;

import com.hashx19.pristinekashmir.MySQLiteHelper;
import com.raizlabs.android.dbflow.annotation.ConflictAction;
import com.raizlabs.android.dbflow.config.FlowManager;
import com.raizlabs.android.dbflow.structure.ModelAdapter;

import java.util.Arrays;
import java.util.HashSet;

/**
 * Created by Filu on 8/25/2016.
 */

public class MyContentProvider extends ContentProvider {

    public static final String AUTHORITY = "com.hashx19.pristinekashmir.mycontentprovider";

    private static final String ENDPOOINT = "feeds";

    // @ContentUri(path = ENDPOOINT, type = ContentUri.ContentType.VND_MULTIPLE + ENDPOOINT)



    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
            + "/" + ENDPOOINT);



    private static final int feeds_CONTENT_URI = 0;

    private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    static {
        MATCHER.addURI(AUTHORITY, ENDPOOINT, feeds_CONTENT_URI);
    }
    ;



    @Override
    public final String getType(Uri uri) {
        String type = null;
        switch(MATCHER.match(uri)) {
            case feeds_CONTENT_URI: {
                type = "vnd.android.cursor.dir/" +ENDPOINT;
                break;
            }
            default: {
                throw new IllegalArgumentException("Unknown URI" + uri);
            }
        }
        return type;
    }

@Override
public boolean onCreate() {
    return false;
}


@Override
public final Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    android.database.Cursor cursor = null;
    switch(MATCHER.match(uri)) {
        case feeds_CONTENT_URI: {
            cursor = FlowManager.getDatabase("AppDatabase").getWritableDatabase().query("TableClassName", projection, selection, selectionArgs, null, null, sortOrder);
            break;
        }
    }
    if (cursor != null) {
        cursor.setNotificationUri(getContext().getContentResolver(), uri);
    }
    return cursor;
}

@Override
public final Uri insert(Uri uri, ContentValues values) {
    switch(MATCHER.match(uri)) {
        case feeds_CONTENT_URI: {
            ModelAdapter adapter = FlowManager.getModelAdapter(FlowManager.getTableClassForName("AppDatabase", "TableClassName"));
            final long id = FlowManager.getDatabase("AppDatabase").getWritableDatabase().insertWithOnConflict("TableClassName", null, values, ConflictAction.getSQLiteDatabaseAlgorithmInt(adapter.getInsertOnConflictAction()));
            getContext().getContentResolver().notifyChange(uri, null);
            return ContentUris.withAppendedId(uri, id);
        }
        default: {
            throw new IllegalStateException("Unknown Uri" + uri);
        }
    }
}


@Override
public final int delete(Uri uri, String selection, String[] selectionArgs) {
    switch(MATCHER.match(uri)) {
        case feeds_CONTENT_URI: {
            long count = FlowManager.getDatabase("AppDatabase").getWritableDatabase().delete("TableClassName", selection, selectionArgs);
            if (count > 0) {
                getContext().getContentResolver().notifyChange(uri, null);
            }
            return (int) count;
        }
        default: {
            throw new IllegalArgumentException("Unknown URI" + uri);
        }
    }
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    switch(MATCHER.match(uri)) {
        case feeds_CONTENT_URI: {
            ModelAdapter adapter = FlowManager.getModelAdapter(FlowManager.getTableClassForName("AppDatabase", "TableClassName"));
            long count = FlowManager.getDatabase("AppDatabase").getWritableDatabase().updateWithOnConflict("TableClassName", values, selection, selectionArgs, ConflictAction.getSQLiteDatabaseAlgorithmInt(adapter.getUpdateOnConflictAction()));
            if (count > 0) {
                getContext().getContentResolver().notifyChange(uri, null);
            }
            return (int) count;
        }
        default: {
            throw new IllegalStateException("Unknown Uri" + uri);
        }
    }
}
}

then when overriding Loader methods do something like this

getLoaderManager().initLoader(1, null, this);




@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {

    String selection, sortOrder;
    String[] selectionArgs, projection;


    selection = ...;

    selectionArgs = ...;

    sortOrder = ...;


    projection= new String[]{"id","date", "link","title","content","excerpt","author",};

    CursorLoader cursorLoader = new CursorLoader(getContext(),MyContentProvider.CONTENT_URI, projection,null,null,null);


    return cursorLoader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {

TableClass post = new TableClass();


      while (!cursor.isAfterLast()) {
      try{
        post.setId(cursor.getInt(cursor.getColumnIndex("id")));



     }catch (NullPointerException e){
          e.printStackTrace();
    }catch (CursorIndexOutOfBoundsException c){
          c.printStackTrace();
    }


     }


}
@Override
public void onLoaderReset(Loader<Cursor> loader) {

}

editted

Figured out easier way to implement content provider .

  1. add this to your manifest / or modify this way if you already have added Provider code .

  2. modify your AppDatabase Class as

    @ContentProvider(authority = AppDatabase.AUTHORITY,
                database = AppDatabase.class,
                baseContentUri = AppDatabase.BASE_CONTENT_URI)
        @Database(name = AppDatabase.NAME, version = AppDatabase.VERSION)
        public class AppDatabase {
    
            public static final String NAME = "AppDatabase"; // we will add the .db extension
    
            public static final int VERSION = 2;
    
            public static final String AUTHORITY = "com.hashx19.pristinekashmir.dbflowcontentprovider";
    
            public static final String BASE_CONTENT_URI = "content://"; }
    
  3. modify each table you want to use as provider as

    @TableEndpoint(name = PostData.ENDPOINT, contentProvider =      AppDatabase.class)
    
    @Table(database =   AppDatabase.class ,allFields = true ,name = PostData.ENDPOINT)
    
    
    
    public class PostData extends BaseModel {
    
        public static final String ENDPOINT = "PostData";
        @ContentUri(path = ENDPOINT, type = ContentUri.ContentType.VND_MULTIPLE + ENDPOINT)
        public static final Uri CONTENT_URI = Uri.parse(AppDatabase.BASE_CONTENT_URI + AppDatabase.AUTHORITY
                + "/" + ENDPOINT);
    
    @PrimaryKey
        public int id;
        public  String image;
    
    }
    
  4. For using Content provider as in Cursor Loader use TableName.CONTENT_URI as in this case

     CursorLoader cursorLoader = new       CursorLoader(getContext(),PostData.CONTENT_URI,projection,null,null,null);