1. 程式人生 > >Android四大應用元件之ContentProvider初探

Android四大應用元件之ContentProvider初探

理解

  1. 首先談一談為什麼要有ContentProvider?

當一個應用想要訪問另一個應用的資料庫時,由於每個應用的資料庫檔案時應用私有的,不能直接訪問,這時,被訪問的應用就需要一個對外的資料庫內容提供者,也就是ContentProvider。

<provider
	<!--自定義ContentProvider需要繼承於ContentProvider,並在功能清單檔案中註冊-->
         android:authorities="com.sank.ar_8_contentprovider_1_bi.personprovider"
          android:name=".PersonProvider"
          android:exported="true"	/>
  1. 什麼是ContentResolver?

ContentResolver又稱內容提供者解析類,用來解析被訪問者暴露的ContentProvider。

  1. 兩者之間的關聯

ContentProvider和ContentResolver之間使用URI進行通訊。

URI:

URI包含URL與URN,是一個包含請求地址的類。

主要使用的兩個工具類:

UriMatcher : 用於匹配Uri的容器

//新增一個合法的URI void addURI(String authority,String path, int code) ;

//匹配指定的uri, 返回匹配碼 int match(Uri uri);

ContentUris : 解析uri的工具類

//解析uri, 得到其中的id long parseId(Uri contentUri)

//新增id到指定的uri中 Uri withAppendedId(Uri contentUri, long id)

Demo

  1. ContentProvider:
  • SQLite資料庫部分:
public class DBHelper extends SQLiteOpenHelper {
    public DBHelper(Context context) {
        super(context, "sank.db", null, 1);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table person(" +
                "_id integer primary key autoincrement," +
                "name varchar(20))");
        db.execSQL("insert into person " +
                "(name) values ('TOM')");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

  • 自定義Provider類:
public class PersonProvider extends ContentProvider {
    //用來存放所有的合法的uri的容器
    private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
    //儲存一些合法的uri
    //content://com.sank.ar_8_contentprovider_1_bi.personprovider/person    不根據id操作
    //content://com.sank.ar_8_contentprovider_1_bi.personprovider/person/3  根據id操作
    static {
        matcher.addURI("com.sank.ar_8_contentprovider_1_bi.personprovider"
                ,"/person",1);
        matcher.addURI("com.sank.ar_8_contentprovider_1_bi.personprovider"
                ,"/person/#",2);
    }
    private DBHelper dbHelper;
    @Override
    public boolean onCreate() {
        dbHelper = new DBHelper(getContext());
        return false;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection,
                        @Nullable String selection, @Nullable String[] selectionArgs,
                        @Nullable String sortOrder) {
        //得到Sql連結物件
        SQLiteDatabase database = dbHelper.getReadableDatabase();
        //匹配uri,返回code
        int code = matcher.match(uri);
        if(code==1){//如何合法,進行查詢
            //不根據id查詢
            Cursor cursor = database.query("person", projection, selection, selectionArgs,
                    null, null, null);
            return cursor;
        }else if(code==2){
            //根據id查詢
            long id = ContentUris.parseId(uri);
            Cursor cursor = database.query("person", projection, "_id=?", new String[]{id + ""},
                    null, null, null);
            return cursor;
        }else{
            //如何不合法,丟擲異常
            throw new RuntimeException("uri不合法");
        }
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        //建立連結
        SQLiteDatabase database = dbHelper.getReadableDatabase();
        //匹配uri,返回code
        int code = matcher.match(uri);
        //檢查uri是否合法
        if(code==1){
            long id = database.insert("person", null, values);
            //將id新增到uri中
            uri = ContentUris.withAppendedId(uri,id);
            database.close();
            return uri;
        }else{
            database.close();
            throw new RuntimeException("uri不合法");
        }
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        //建立連結
        SQLiteDatabase database = dbHelper.getReadableDatabase();
        //匹配uri,返回code
        int code = matcher.match(uri);
        //刪除的個數
        int deleteCount = -1;
        //檢查uri是否合法
        if(code==1){
            deleteCount = database.delete("person", selection, selectionArgs);
        }else if(code ==2){
            long id = ContentUris.parseId(uri);
            database.delete("person", "_id=" + id, null);
        } else{
            database.close();
            throw new RuntimeException("uri不合法");
        }
        database.close();
        return deleteCount;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        //建立資料庫連結
        SQLiteDatabase database = dbHelper.getReadableDatabase();
        //匹配uri
        int code = matcher.match(uri);
        //更新的行數
        int updateCount;
        //檢查是否合法
        if (code == 1) {
            updateCount = database.update("person", values, selection, selectionArgs);
        } else if (code == 2) {
            long id = ContentUris.parseId(uri);
            updateCount = database.update("person", values, "_id=" + id, null);
        }else {
            database.close();
            throw new RuntimeException("uri不合法");
        }
        database.close();
        return updateCount;
    }
}
  1. ContentResolver:
public class MainActivity extends AppCompatActivity {

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

    /*
        CRUD
     */
    public void insert(View view) {
        //得到ContentResolver物件
        ContentResolver resolver = getContentResolver();
        Uri uri = Uri.parse("content://com.sank.ar_8_contentprovider_1_bi.personprovider/person/");
        ContentValues values = new ContentValues();
        values.put("name","mary");
        uri = resolver.insert(uri,values);
        Toast.makeText(this,uri.toString(),Toast.LENGTH_SHORT).show();
    }

    public void delete(View view) {
        ContentResolver resolver = getContentResolver();
        Uri uri = Uri.parse("content://com.sank.ar_8_contentprovider_1_bi.personprovider/person/2");
        int deleteCount = resolver.delete(uri,null, null);
        Toast.makeText(this,"deleteCount="+deleteCount,Toast.LENGTH_SHORT).show();
    }

    public void update(View view) {
        ContentResolver resolver = getContentResolver();
        Uri uri = Uri.parse("content://com.sank.ar_8_contentprovider_1_bi.personprovider/person/1");
        ContentValues values = new ContentValues();
        values.put("name","Tom2");
        int updateCount = resolver.update(uri, values, null, null);
        Toast.makeText(this,"updateCount="+updateCount,Toast.LENGTH_SHORT).show();
    }

    public void query(View view) {
        //得到ContentResolver物件
        ContentResolver resolver = getContentResolver();
        //呼叫query,得到cursor物件
        Uri uri = Uri.parse("content://com.sank.ar_8_contentprovider_1_bi.personprovider/person");
        Cursor cursor = resolver.query(uri, null, null, null, null);
        //取出cursor中的資料
        assert cursor != null;
        while(cursor.moveToNext()){
            int id = cursor.getInt(0);
            String name = cursor.getString(1);
            Toast.makeText(this,id+" : "+name,Toast.LENGTH_SHORT).show();
        }
        cursor.close();
    }
}