ContentProvider с несколькими таблицами - PullRequest
7 голосов
/ 27 марта 2012

Я хочу реализовать 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. Должен ли я изменить интерфейс и предоставить каждому методу CRUD этот объект Dependency Injection, чтобы позволить каждой функции использовать его для доступа к базе данных? Я также хочу знать, что вы думаете об этом подходе: он достаточно хорош? Делает ли это то, что я пытаюсь сделать эффективно? Какие модификации я могу сделать, чтобы улучшить этот дизайн?

Ответы [ 3 ]

10 голосов
/ 04 апреля 2012

Приложение Google IO Schedule является хорошим ресурсом, если вам необходимо создать ContentProvider с несколькими таблицами. Похоже, вы хотите сделать что-то более сложное, но, возможно, это поможет.

2 голосов
/ 08 февраля 2013

Почему бы вам не создать несколько таблиц под провайдером контента таким образом.

Предположим, у вас есть две таблицы с именами 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);
     }

Теперь вы можете реализовать переопределенные методы, используя стандартный регистр переключения и правильно сопоставляя методы базового класса базы данных SQLite.

2 голосов
/ 04 апреля 2012

Я прошел проект с открытым исходным кодом, в котором они использовали несколько таблиц. Вы можете посмотреть на различные проекты OpenIntents и вот аналогичный вопрос .
Надеюсь, это может вам помочь.

...