組件之ContentProvider全面解析

一、ContentProvider使用

(1)ContentProvider方法

  • onCreate:創(chuàng)建ContentProvider后調(diào)用
  • getType:返回當(dāng)前Uri所代表數(shù)據(jù)的MIME類型
  • query:用于供外部應(yīng)用從ContentProvider中查詢數(shù)據(jù)
  • insert:用于供外部應(yīng)用向ContentProvider中增加數(shù)據(jù)
  • delete:用于供外部應(yīng)用從ContentProvider中刪除數(shù)據(jù)
  • update:用于供外部應(yīng)用更新ContentProvider中數(shù)據(jù)
    (2)SQLiteOpenHelper類的實(shí)現(xiàn)
public class DBOpenHelper extends SQLiteOpenHelper {

    public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //創(chuàng)建表student
        db.execSQL("create table if not exists animal(" +
                "_id integer primary key autoincrement, " +
                "name text not null , " +
                "age integer not null , " +
                "sex text not null)");
        db.execSQL("create table if not exists person(" +
                "_id integer primary key autoincrement, " +
                "name text not null , " +
                "age integer not null , " +
                "sex text not null)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        switch (oldVersion) {
            case 1:
                db.execSQL("create table if not exists person(" +
                        "_id integer primary key autoincrement, " +
                        "name text not null , " +
                        "age integer not null , " +
                        "sex text not null)");
                break;
        }
    }
}

(3)ContentProvider 類的實(shí)現(xiàn)

public class MyContentProvider extends ContentProvider {
    public DBOpenHelper dbOpenHelper;
    public static UriMatcher uriMatcher;
    public static final int ANIMAL_DIR = 1001;
    public static final int ANIMAL_ITEM = 1002;
    public static final int PERSON_DIR = 1003;
    public static final int PERSON_ITEM = 1004;
    public static final String AUTHORITIES = "com.example.dbsqlite.mycontentprovider";

    //對(duì)UriMatcher進(jìn)行了初始化
    //id用以區(qū)分表中不同的數(shù)據(jù)記錄,如果沒有id就返回全部。用到了轉(zhuǎn)義符。#代表任意數(shù)字,*代表任意字母。
    static {
        uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(AUTHORITIES, "animal", ANIMAL_DIR);
        uriMatcher.addURI(AUTHORITIES, "animal/#", ANIMAL_ITEM);
        uriMatcher.addURI(AUTHORITIES, "person", PERSON_DIR);
        uriMatcher.addURI(AUTHORITIES, "person/#", PERSON_ITEM);
    }

    /**
     * 該方法在ContentProvider被其它應(yīng)用第一次訪問它時(shí)才會(huì)被創(chuàng)建
     * 返回true表示內(nèi)容提供器初始化成功
     *
     * @return
     */
    @Override
    public boolean onCreate() {
        dbOpenHelper = new DBOpenHelper(getContext(), "UserInfo.db", null, 2);
        return true;
    }

    /**
     * 用于供外部應(yīng)用從ContentProvider中查詢數(shù)據(jù)
     *
     * @param uri
     * @param projection
     * @param selection
     * @param selectionArgs
     * @param sortOrder
     * @return
     */
    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        String id;
        Cursor cursor = null;
        //獲取到SQLiteDatabase的實(shí)例
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
        //判斷用戶查詢哪張表
        switch (uriMatcher.match(uri)) {
            case ANIMAL_DIR:
                cursor = db.query("animal", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case ANIMAL_ITEM:
                //調(diào)用Uri對(duì)象的getPathSegments()方法
                //它會(huì)將內(nèi)容URI權(quán)限之后的部分以“/”符號(hào)進(jìn)行分割,并把分割后的結(jié)果放入到一個(gè)字符串列表中,
                //那這個(gè)列表的第0個(gè)位置存放的就是路徑,第1個(gè)位置存放的就是id
                id = uri.getPathSegments().get(1);
                cursor = db.query("animal", projection, "id=?", new String[]{id}, null, null, sortOrder);
                break;
            case PERSON_DIR:
                cursor = db.query("person", projection, selection, selectionArgs, null, null, sortOrder);
                break;
            case PERSON_ITEM:
                id = uri.getPathSegments().get(1);
                cursor = db.query("person", projection, "id=?", new String[]{id}, null, null, sortOrder);
                break;
        }
        return cursor;
    }

    /**
     * 返回當(dāng)前Uri所代表數(shù)據(jù)的MIME類型
     * 內(nèi)容URI所對(duì)應(yīng)的MIME字符串主要由三部分組分,
     * Android對(duì)這三個(gè)部分做了以下格式規(guī)定:必須以vnd開頭;
     * 如果內(nèi)容URI以路徑結(jié)尾,則后接android.cursor.dir/,
     * 如果內(nèi)容URI以id結(jié)尾,則后接android.cursor.item/;
     * 最后接上vnd.< authority>.< path>。
     *
     * @param uri
     * @return
     */
    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        //與已經(jīng)注冊(cè)的Uri進(jìn)行匹配
        switch (uriMatcher.match(uri)) {
            case ANIMAL_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.dbsqlite.mycontentprovider.animal";
            case ANIMAL_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.dbsqlite.mycontentprovider.animal";
            case PERSON_DIR:
                return "vnd.android.cursor.dir/vnd.com.example.dbsqlite.mycontentprovider.person";
            case PERSON_ITEM:
                return "vnd.android.cursor.item/vnd.com.example.dbsqlite.mycontentprovider.person";
        }
        return null;
    }

    /**
     * 用于供外部應(yīng)用向ContentProvider中增加數(shù)據(jù)
     *
     * @param uri
     * @param values
     * @return
     */
    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
        Uri uri_return = null;
        long id;
        //判斷向哪張表里添加數(shù)據(jù)
        switch (uriMatcher.match(uri)) {
            case ANIMAL_DIR:
            case ANIMAL_ITEM:
                id = db.insert("animal", null, values);
                uri_return = Uri.parse("content://" + AUTHORITIES + "/animal/" + id);
                break;
            case PERSON_DIR:
            case PERSON_ITEM:
                id = db.insert("person", null, values);
                uri_return = Uri.parse("content://" + AUTHORITIES + "/person/" + id);
                break;
        }
        return uri_return;
    }

    /**
     * 用于供外部應(yīng)用從ContentProvider中刪除數(shù)據(jù)
     *
     * @param uri
     * @param selection
     * @param selectionArgs
     * @return
     */
    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        String id;
        int row = 0;
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
        switch (uriMatcher.match(uri)) {
            case ANIMAL_DIR:
                row = db.delete("animal", selection, selectionArgs);
                break;
            case ANIMAL_ITEM:
                id = uri.getPathSegments().get(1);
                row = db.delete("animal", "id=?", new String[]{id});
                break;
            case PERSON_DIR:
                row = db.delete("person", selection, selectionArgs);
                break;
            case PERSON_ITEM:
                id = uri.getPathSegments().get(1);
                row = db.delete("person", "id=?", new String[]{id});
                break;
        }
        return row;
    }

    /**
     * 用于供外部應(yīng)用更新ContentProvider中數(shù)據(jù)
     *
     * @param uri
     * @param values
     * @param selection
     * @param selectionArgs
     * @return
     */
    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        String id;
        int row = 0;
        SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
        switch (uriMatcher.match(uri)) {
            case ANIMAL_DIR:
                row = db.update("animal", values, selection, selectionArgs);
                break;
            case ANIMAL_ITEM:
                id = uri.getPathSegments().get(1);
                row = db.update("animal", values, "id=?", new String[]{id});
                break;
            case PERSON_DIR:
                row = db.update("person", values, selection, selectionArgs);
                break;
            case PERSON_ITEM:
                id = uri.getPathSegments().get(1);
                row = db.update("person", values, "id=?", new String[]{id});
                break;
        }
        return row;
    }
}

(5)在配置文件中進(jìn)行注冊(cè),并注明屬性

        <!--authorities設(shè)置Provider的權(quán)限-->
        <!--exported指明該P(yáng)rovider可被其它程序訪問-->
        <provider
            android:name=".MyContentProvider"
            android:authorities="ccom.example.dbsqlite.mycontentprovider"
            android:exported="true"
            android:readPermission="com.example.provider.myprovider" />

(6)ContentResolver方法

  • insert:用于往ContentProvider添加數(shù)據(jù)。
  • delete:用于從ContentProvider刪除數(shù)據(jù)。
  • query:用于從ContentProvider中獲取數(shù)據(jù)。
  • update:用于更新ContentProvider中的數(shù)據(jù)。

(7)數(shù)據(jù)的增刪改查操作

    private ContentValues values;
    private ContentResolver resolver;
    private Uri uri;
    private Uri uri_new;
    private Uri uri_return;

    public void init() {
        values = new ContentValues();
        resolver = getContentResolver();
        uri = Uri.parse("com.example.dbsqlite.mycontentprovider/animal");
    }

    public void insert() {
        values.put("name", "cat");
        values.put("age", 2);
        values.put("sex", "male");
        uri_return = resolver.insert(uri, values);
        values.clear();
        values.put("name", "tiger");
        values.put("age", 2);
        values.put("sex", "male");
        uri_return = resolver.insert(uri, values);
        String id = uri_return.getPathSegments().get(1);
        uri_new = Uri.parse("content://com.example.dbsqlite.mycontentprovider/animal" + id);
        values.clear();
        values.put("name", "lion");
        values.put("age", 4);
        values.put("sex", "female");
        uri_return = resolver.insert(uri, values);
        values.clear();
    }

    public void delete() {
        resolver.delete(uri_new, null, null);
    }

    public void update() {
        values.put("age", 5);
        resolver.update(uri, values, "age=?", new String[]{"4"});
    }

    public void query() {
        Cursor cursor = resolver.query(uri, null, null, null, null);
        if (cursor != null) {
            while (cursor.moveToFirst()) {
                String name = cursor.getString(cursor.getColumnIndex("name"));
            }
            cursor.close();
        }
    }

二、ContentProvider源碼解析

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容