淺析 - Android ContentProvider用法示例

尊重每個人的付出,轉載請點這裏: http://blog.csdn.net/hanj456/article/details/52621150

作爲Android的四大組件之一,也許你平時開發中根本沒有用到過ContentProvider,但你還是需要掌握它的一些基本操作步驟,任何看起來挺複雜的東西拆開來看就那麼回事,下面還是先進入我們的“三問三答”環節:

ContentProvider之“三問三答”

問:ContentProvider是什麼?
答:Android四大組件之一(Activity ,Service , BroadcastReceiver ,ContentProvider),向我們提供了在不同應用程序之間共享數據的一種機制,統一了應用之間數據訪問的方式。

問:ContentProvider的作用?
答:簡單來說它的作用就是爲不同應用之間存儲和獲取數據提供了統一的接口,比較常用到的是共享視頻,音頻,圖片,通訊錄這些資源。

問:ContentProvider如何使用?
答:因爲相比其他三個組件來說它不常用到,而且看到繼承ContentProvider需要實現六個方法,很多人一下子被嚇到了,其實仔細看會發現除去對數據基本的增刪改查和onCreate()外,也就剩下一個getType()沒見過的方法,這樣分析下來是不是就感覺輕鬆很多呢?其實要掌握ContentProvider的基本用法主要記住以下四個API的用法就行:

  1. UriMatcher.match() //主要是對Uri進行匹配;
  2. ContentResolver.notifyChange() //主要是對數據進行刷新;
  3. ContentUris.parseId() //主要是對Uri進行解析;
  4. ContentUris.withAppendedId() //主要是給Uri添加ID

下面我將以一個簡單的Demo爲例,分解說明使用ContentProvider實現不同應用之間數據 共享操作需要哪些步驟:
有兩個應用:應用A(獲取操作數據的一方)和應用B(共享數據的一方)

Step1

在應用B中創建數據資源,這裏我新建一個sqlite表 students,添加_id , name , age三個字段:

public class DBHelper extends SQLiteOpenHelper {


    private static SQLiteOpenHelper mInstance;
    public synchronized static SQLiteOpenHelper getInstance(Context context){
        if (mInstance==null){
            mInstance = new DBHelper(context,"test.db",null,1);
        }
        return mInstance;
    }
    private DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE students(_id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,age INTEGER)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

Step2

新建一個常量類,提前準備幾個需要用到的常量數據

public class Const {

    public static final String TABLE_NAME = "students";

    public static final String AUTHORITY = "com.test.provider2";

    public static final class Student implements BaseColumns {
        public static final String ID = "_id";
        public static final String NAME = "name";
        public static final String AGE = "age";

        public static final Uri DIR_STUDENTS_URI = Uri.parse("content://" + AUTHORITY + "/students");
        public static final Uri ITEM_STUDENT_URI = Uri.parse("content://" + AUTHORITY + "/student");
    }
}

Step3

新建一個ContentProvider子類繼承ContentProvider

public class MyProvider extends ContentProvider {

    private static UriMatcher mMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    private static final int STUDENTS = 1;

    private static final int STUDENT = 2;

    static {
        mMatcher.addURI(Const.AUTHORITY, "students", STUDENTS);
        mMatcher.addURI(Const.AUTHORITY, "student/#", STUDENT);
    }

    private SQLiteOpenHelper mHelper;
    private ContentResolver mResolver;

    @Override
    public boolean onCreate() {
        mHelper = DBHelper.getInstance(getContext());
        mResolver = getContext().getContentResolver();
        return true;//設置爲true表示provider創建生效
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = mHelper.getReadableDatabase();
        switch (mMatcher.match(uri)) {
            case STUDENTS:
                return db.query(Const.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
            case STUDENT:
                long id = ContentUris.parseId(uri);
                String condition = Const.Student.ID + "=" + id;
                if (selection != null && !selection.equals("")) {
                    condition = condition + " and " + selection;
                }
                return db.query(Const.TABLE_NAME, projection, condition, selectionArgs, null, null, sortOrder);
            default:
                throw new IllegalArgumentException("未知的Uri:" + uri);
        }
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        switch (mMatcher.match(uri)) {
            case STUDENTS:
                return "vnd.android.cursor.dir/com.test.provider2"; //前半部分是規定的寫法,表示這是一個查詢全部數據的類型,後半部分是自定義的
            case STUDENT:
                return "vnd.android.cursor.item/com.test.provider2";//前半部分是規定的寫法,表示這是一個查詢單條數據的類型,後半部分是自定義的
            default:
                throw new IllegalArgumentException("未知的Uri:" + uri);
        }
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {

        SQLiteDatabase db = mHelper.getWritableDatabase();

        if (mMatcher.match(uri) != STUDENTS) {
            throw new IllegalArgumentException("未知的Uri:" + uri);
        }

        long id = db.insert(Const.TABLE_NAME, Const.Student.ID, values);

        if (id < 0) {
            throw new SQLiteException("插入數據失敗!");
        }

        Uri newUri = ContentUris.withAppendedId(uri, id);
        mResolver.notifyChange(uri, null);
        return newUri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        SQLiteDatabase db = mHelper.getWritableDatabase();
        int deleteNum = -1;
        switch (mMatcher.match(uri)) {
            case STUDENTS:
                deleteNum = db.delete(Const.TABLE_NAME, selection, selectionArgs);
                break;
            case STUDENT:
                long id = ContentUris.parseId(uri);
                String condition = Const.Student.ID + "=" + id;
                if (selection != null && !selection.equals("")) {
                    condition = condition + " and " + selection;
                }
                deleteNum = db.delete(Const.TABLE_NAME, condition, selectionArgs);
                break;
            default:
                throw new IllegalArgumentException("未知的Uri:" + uri);
        }
        mResolver.notifyChange(uri,null);
        return deleteNum;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        SQLiteDatabase db = mHelper.getWritableDatabase();
        int updateNum = -1;
        switch (mMatcher.match(uri)) {
            case STUDENTS:
                updateNum = db.update(Const.TABLE_NAME, values, selection, selectionArgs);
                break;
            case STUDENT:
                long id = ContentUris.parseId(uri);
                String condition = Const.Student.ID + "=" + id;
                if (selection != null && !selection.equals("")) {
                    condition = condition + " and " + selection;
                }
                updateNum = db.update(Const.TABLE_NAME, values, condition, selectionArgs);
                break;
            default:
                throw new IllegalArgumentException("未知的Uri:" + uri);
        }
        mResolver.notifyChange(uri,null);
        return updateNum;
    }
}

Step4

在清單文件中配置provider

<provider
      android:authorities="com.test.provider2"
      android:name=".second.MyProvider"
      android:exported="true"/>//設置爲true表示允許對外共享數據

Step5

經過上面5步ContentProvider的基本步驟就算完成了,剩下的就是在應用A中去獲取和操作應用B中的數據了,因爲要獲取應用B中的數據,必須知道ContentProvider中對外提供的字段,也就是應用B中的常量數據,所以最好先把該常量類Const.java 拷貝到應用A中方便使用,應用A中MainActivity 佈局文件很簡單,就只有四個按鈕分別對應:增,刪,改,查;

這裏寫圖片描述

public class MainActivity extends AppCompatActivity {

    private ContentResolver mResolver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mResolver = getContentResolver();
    }

    public void add(View v){
        ContentValues values = new ContentValues();
        values.put(Const.Student.NAME,"小明");
        values.put(Const.Student.AGE,16);
        mResolver.insert(Const.Student.DIR_STUDENTS_URI,values);
        values.put(Const.Student.NAME,"小強");
        values.put(Const.Student.AGE,17);
        mResolver.insert(Const.Student.DIR_STUDENTS_URI,values);
        Toast.makeText(this,"添加數據成功",Toast.LENGTH_SHORT).show();
    }

    public void update(View v){
        ContentValues values = new ContentValues();
        values.put(Const.Student.AGE,28);
        mResolver.update(Const.Student.DIR_STUDENTS_URI,values,"name like ?",new String[]{"小明"});
        Toast.makeText(this,"更新數據成功",Toast.LENGTH_SHORT).show();
    }

    public void delete(View v){
        mResolver.delete(Const.Student.DIR_STUDENTS_URI,"name like ?",new String[]{"小明"});
        Toast.makeText(this,"刪除數據成功",Toast.LENGTH_SHORT).show();
    }

    public void query(View v){
        Cursor cursor = mResolver.query(Const.Student.DIR_STUDENTS_URI, null, null, null, null);
        int count = cursor.getCount();
        if (count<1){
            Toast.makeText(this,"數據爲空!",Toast.LENGTH_SHORT).show();
            return;
        }
        while (cursor.moveToNext()){
            String name = cursor.getString(1);
            String age = cursor.getString(2);
            Toast.makeText(this,"name="+name+" ,age="+age,Toast.LENGTH_SHORT).show();
        }
    }
}

好了,到此應用A通過ContentProvider操作應用B中的數據實驗成功,這裏我主要是講使用ContentProvider的基本步驟,至於上面所提到的那幾個API的細節大家有興趣可以花點時間去查看官方文檔說明,理清楚思路很重要,很多東西都沒有看上去那麼難!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章