ContentProvider具有多个表

时间:2012-03-27 00:25:52

标签: java android design-patterns android-contentprovider

我想实现一个操作多个表的ContentProvider。这是我到目前为止所尝试的。我编写了一个Java Interface,它表示每个表应在其CRUD类中实现的CRUD操作。

public interface CRUDHandler {
    //UPDATE
    int update(Uri uri, ContentValues values, String selection,String[] selectionArgs);
    //READ
    Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) ;
    //CREATE
    Uri insert(Uri uri, ContentValues values);
    //DELETE
    int delete(Uri uri, String selection, String[] selectionArgs);
    //get Mime type
    String getType(Uri uri);
}

然后我写了一个abstract class,为UriMatcher定义了一个静态ContentProvider,因此extends这个类应添加其Uri的每个类标识它并为接口中的每个方法提供实现。

该课程如下:

public abstract class  ApplicationCRUD  implements CRUDHandler{

    public static final UriMatcher sUriMatcher;

    static {
        sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    }
}

此外,我为每个extends这个类的表创建了一个类,并将其Uri添加到抽象类的UriMatcher中。

以下是一个例子:

public class Table1CRUD extends ApplicationCRUD {
    //Setup Projection Map for Table1 
        private static HashMap<String , String>sTable1ProjectionMap;
        static {
            sTable1ProjectionMap.put(ApplicationProviderMetaData.Table1MetaData._ID, ApplicationProviderMetaData.Table1MetaData.TABLE_NAME+"."+ApplicationProviderMetaData.Table1MetaData._ID);
            sTable1ProjectionMap.put(ApplicationProviderMetaData.Table1MetaData.COL1, ApplicationProviderMetaData.Table1MetaData.TABLE_NAME+"."+ApplicationProviderMetaData.Table1MetaData.COL1);
            sTable1ProjectionMap.put(ApplicationProviderMetaData.Table1MetaData.COL2, ApplicationProviderMetaData.Table1MetaData.TABLE_NAME+"."+ApplicationProviderMetaData.Table1MetaData.COL2);
        }

        public static final int INCOMING_SINGLE_URI_INDICATOR = 5;
        public static final int INCOMING_COLLECTION_URI_INIDICATOR = 6;
    static {
        //standard URI 
        sUriMatcher.addURI(ApplicationProviderMetaData.AUTHORITY, "t1", INCOMING_COLLECTION_URI_INIDICATOR);
        sUriMatcher.addURI(ApplicationProviderMetaData.AUTHORITY, "t1/#", INCOMING_SINGLE_URI_INDICATOR);
        //here add your custom URI 

    }
    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public String getType(Uri uri) {
        // TODO Auto-generated method stub
        return null;
    }

}

现在我的ContentProvider看起来像这样:

public class ApplicationProvider  extends ContentProvider{
    //Define TAG FOR EACH CLASS FOR DEBUGGING 
    private static final String TAG = "ApplicationProvider";
    // Application CRUD Handlers use to support multiple tables inside the content provider
    private static Table1CRUD table1CRUD;
    private static Table2CRUD table2CRUD;

    static {
        table1CRUD = new Table1CRUD();
        table2CRUD= new Table2CRUD();

    }
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        int uriMatchResult = ApplicationCRUD.sUriMatcher.match(uri);
        //case Table1
        if(uriMatchResult == Table1CRUD.INCOMING_COLLECTION_URI_INIDICATOR ||uriMatchResult == Table1CRUD.INCOMING_SINGLE_URI_INDICATOR )
        {
            return table1CRUD.delete(uri, selection, selectionArgs);
        }
        case Table2
        else if(uriMatchResult == Table2.INCOMING_COLLECTION_URI_INDICATOR|| uriMatchResult ==Table2.INCOMING_SINGLE_URI_INDICATOR){
            return table2CRUD.delete(uri, selection, selectionArgs);
        }

        else{
            throw new IllegalArgumentException("Unknown Uri "+uri);
        }
    }

现在我使用SQLiteOpenHelper作为ContentProvider中的私有类 我在ContentProvider中定义了它的一个实例。我应该修改接口并提供对象Dependency Injection的每个CRUD方法,让每个函数使用它来访问数据库吗?我也想知道你对这种方法的看法:它足够好吗?它是否使我想要有效地做的事情?我可以做些什么修改来改进这种设计?

3 个答案:

答案 0 :(得分:10)

如果您需要设计具有多个表的ContentProviderGoogle IO Schedule应用程序是一个很好的资源。听起来你想要做一些更复杂的事情,但也许它会有所帮助。

答案 1 :(得分:2)

我已经完成了开源项目,他们使用了多个表。您可以查看OpenIntents的各种项目,这里是similar question 我希望,它可以帮到你。

答案 2 :(得分:2)

为什么不以这种方式在内容提供商下制作多个表格。

假设您有两个名为A和B的表,它们的URI将是AUTHORITY / A,AUTHORITY / B

private static final int TableOne = 1; 
private static final int TableTwo = 2;

private static final UriMatcher uriMatcher;
static{
       uriMatcher.addUri(AUTHORITY,"A",TableOne);
       uriMatcher.addUri(AUTHORITY,"B",TableTwo);
     }

现在,您可以使用标准switch case实现重写方法,并正确映射到基础SQLite Database类的方法。