简体   繁体   中英

Better way to create Android content providers

I have a content provider in my app and I really don't like it :-). The provider is created after reading number of articles like the official one and this unofficial one .

What I really don't like is the amount of duplication in the provider class (see very stripped down code below). Even for two (or four, it depends on how you count) content types there is too much code.

I thought about going the other route: raw SQL queries in the content provider but not sure if this will turn out to be more elegant.

Please advise a better way to create Android content providers then the one in the code below.

public abstract class BaseProvider extends ContentProvider
{
    protected DatabaseHelper m_helper;

    protected static class DatabaseHelper extends SQLiteOpenHelper
    {
        private static final String DATABASE_NAME = "my.db";
        private static final int DATABASE_VERSION = 4;

        public DatabaseHelper(Context context)
        {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db)
        {
            FolderTable.onCreate(db);
            TrackTable.onCreate(db);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
        {
            FolderTable.onUpgrade(db, oldVersion, newVersion);
            TrackTable.onUpgrade(db, oldVersion, newVersion);
        }
    }

    @Override
    public boolean onCreate()
    {
        m_helper = new DatabaseHelper(getContext());
        return true;
    }
    // ...
}


public class MyProvider extends BaseProvider
{    
    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    private static final int FOLDERS = 10;
    private static final int FOLDER_ID = 20;
    private static final int TRACKS = 30;
    private static final int TRACK_ID = 40;

    private static final String FOLDERS_BASE_PATH = "folders";
    private static final String TRACKS_BASE_PATH = "tracks";

    public static final String AUTHORITY = ".contentprovider.MyProvider";
    private static final String CONTENT_URI_BASE = "content://" + AUTHORITY + "/";

    public static final Uri FOLDERS_CONTENT_URI = Uri.parse(CONTENT_URI_BASE + FOLDERS_BASE_PATH);
    public static final Uri TRACKS_CONTENT_URI = Uri.parse(CONTENT_URI_BASE + TRACKS_BASE_PATH);

    static
    {
        sURIMatcher.addURI(AUTHORITY, FOLDERS_BASE_PATH, FOLDERS);
        sURIMatcher.addURI(AUTHORITY, FOLDERS_BASE_PATH + "/#", FOLDER_ID);
        sURIMatcher.addURI(AUTHORITY, TRACKS_BASE_PATH, TRACKS);
        sURIMatcher.addURI(AUTHORITY, TRACKS_BASE_PATH + "/#", TRACK_ID);
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder)
    {
        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();

        int uriType = sURIMatcher.match(uri);
        switch (uriType)
        {
            case FOLDERS:
                queryBuilder.setTables(getTablesForFolders());
                break;

            case FOLDER_ID:
                queryBuilder.setTables(FolderTable.TABLE_NAME);
                queryBuilder.appendWhere(FolderTable.COLUMN_ID + "=" + uri.getLastPathSegment());
                break;

            case TRACKS:
                queryBuilder.setTables(getTablesForTracks());
                break;

            case TRACK_ID:
                queryBuilder.setTables(TrackTable.TABLE_NAME);
                queryBuilder.appendWhere(TrackTable.COLUMN_ID + "=" + uri.getLastPathSegment());
                break;

        default:
                throw new IllegalArgumentException("Unknown URI: " + uri);
        }

        SQLiteDatabase db = m_helper.getWritableDatabase();
        if (db == null)
            return null;

        Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
        if (cursor == null)
            return null;

        setNotificationUri(cursor, uri);

        return cursor;
    }    
    // ....
}

Use different class to implement ContentProvider and DatabaseHelper. See example exactly not your's example something different but you will get idea by seeing it.

DatabaseHelper.java

public class DatabaseHelper extends SQLiteOpenHelper{

private static final String name="mybooks.sdb";
private static final int version=1;
private static final CursorFactory factory=null;
public DatabaseHelper(Context context)
{
    super(context,name,factory,version);
}
@Override
public void onCreate(SQLiteDatabase database) {
    // TODO Auto-generated method stub
    database.execSQL("create table mybooks(code INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,author TEXT)");
}

@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
    // TODO Auto-generated method stub

}
public long insert(ContentValues contentValues)
{
    long x;
    SQLiteDatabase database=this.getWritableDatabase();
    x=database.insert("mybooks",null, contentValues);
    database.close();
    return x;
}
public Cursor query(String[] columns,String whereClause,String[] replaceQuestionMarksWith,String orderBy)
{
    SQLiteDatabase database=this.getReadableDatabase();
    return database.query("mybooks", columns, whereClause, replaceQuestionMarksWith, null, null, orderBy);
}
public int update(ContentValues contentValues,String whereClause,String[] replaceQuestionMarksWith)
{
    SQLiteDatabase database=this.getWritableDatabase();
    int numberOfRecordsUpdated=database.update("mybooks", contentValues, whereClause, replaceQuestionMarksWith);
    database.close();
    return numberOfRecordsUpdated;
}
public int delete(String whereClause,String[] replaceQuestionMarksWith)
{
    SQLiteDatabase database=this.getWritableDatabase();
    int numberOfRecordsDeleted=database.delete("mybooks", whereClause, replaceQuestionMarksWith);
    database.close();
    return numberOfRecordsDeleted;
}

}

and ContentProvider.java as

    public class MyBookProvider extends ContentProvider{
    private DatabaseHelper databaseHelper;
    private static final UriMatcher uriMatcher;
    private static final int INCOMING_BOOK_COLLECTION_URI_INDICATOR = 1;
    private static final int INCOMING_ONE_BOOK_URI_INDICATOR = 2;

    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);               
        uriMatcher.addURI(LibraryContentProviderMetaData.AUTHORITY, "books",INCOMING_BOOK_COLLECTION_URI_INDICATOR);        
        uriMatcher.addURI(LibraryContentProviderMetaData.AUTHORITY, "books/#",INCOMING_ONE_BOOK_URI_INDICATOR); 
    }
@Override
    public String getType(Uri uri) 
    {
        String mimeType;
        switch(uriMatcher.match(uri))
        {
            case INCOMING_BOOK_COLLECTION_URI_INDICATOR:
                mimeType=LibraryContentProviderMetaData.CONTENT_TYPE;
                break;
            case INCOMING_ONE_BOOK_URI_INDICATOR:
                mimeType=LibraryContentProviderMetaData.CONTENT_ITEM_TYPE;
                break;
            default:throw new IllegalArgumentException("Invalid URI"+uri);
        }
        return mimeType;
    }
@Override
    public Uri insert(Uri uri, ContentValues contentValues) {
        // TODO Auto-generated method stub
        if (uriMatcher.match(uri) != INCOMING_BOOK_COLLECTION_URI_INDICATOR) 
        {
            throw new IllegalArgumentException("Invalid URI " + uri);
        }
        long x = databaseHelper.insert(contentValues);
        return Uri.parse("content//com.lib.mybooks.MyBookProvider/books/" + x);
    }
    @Override
    public boolean onCreate() {     
        databaseHelper = new DatabaseHelper(getContext());
        return true;
    }
    @Override
    public Cursor query(Uri uri, String[] columns, String whereClause,String[] replaceQuestionMarksWith, String orderBy) 
    {
        switch (uriMatcher.match(uri)) 
        {
        case INCOMING_BOOK_COLLECTION_URI_INDICATOR:break;
        case INCOMING_ONE_BOOK_URI_INDICATOR:whereClause = "code=?";
            replaceQuestionMarksWith = new String[] { uri.getPathSegments().get(1) };
            break;
        default:throw new IllegalArgumentException("Invalid URI " + uri);
        }
        Cursor cursor = databaseHelper.query(columns, whereClause,replaceQuestionMarksWith, orderBy);
        return cursor;
    }
    @Override
    public int update(Uri uri, ContentValues contentValues, String whereClause, String[] replaceQuestionMarksWith) 
    {
        if(uriMatcher.match(uri)!=INCOMING_BOOK_COLLECTION_URI_INDICATOR)
        {
            throw new IllegalArgumentException("Invalid URI "+uri);
        }

        return databaseHelper.update(contentValues, whereClause,replaceQuestionMarksWith);
    }
    @Override
    public int delete(Uri uri, String whereClause, String[] replaceQuestionMarksWith) 
    {
        if(uriMatcher.match(uri)!=INCOMING_BOOK_COLLECTION_URI_INDICATOR)
        {
            throw new IllegalArgumentException("Invalid URI "+uri);
        }
        return databaseHelper.delete(whereClause, replaceQuestionMarksWith);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM