Android開(kāi)發(fā):ContentProvider實(shí)例詳解

  • 2016年12月8日,Google中國(guó)開(kāi)發(fā)者大會(huì)在京舉行,同時(shí)正式上線了Google中國(guó)開(kāi)發(fā)者網(wǎng)站Google Developers,查看官方學(xué)習(xí)資源再也不用爬梯子了
  1. 簡(jiǎn)介
  2. 使用說(shuō)明
  3. ContentObserver

簡(jiǎn)介

ContentProvider即內(nèi)容提供者,是Android的四大組件之一。內(nèi)容提供者是應(yīng)用程序之間共享數(shù)據(jù)的接口,Android系統(tǒng)將這種機(jī)制應(yīng)用到方方面面。

比如:聯(lián)系人Provider專為不同應(yīng)用程序提供聯(lián)系人數(shù)據(jù);設(shè)置Provider專為不同應(yīng)用程序提供系統(tǒng)配置信息,包括內(nèi)置的設(shè)置應(yīng)用程序等。當(dāng)應(yīng)用繼承ContentProvider類,并重寫該類用于提供數(shù)據(jù)和存儲(chǔ)數(shù)據(jù)的方法,就可以向其他應(yīng)用共享其數(shù)據(jù)。

雖然使用其他方法也可以對(duì)外共享數(shù)據(jù),但數(shù)據(jù)訪問(wèn)方式會(huì)因數(shù)據(jù)存儲(chǔ)的方式而不同,如:采用文件方式對(duì)外共享數(shù)據(jù),需要進(jìn)行文件操作讀寫數(shù)據(jù);采用SharedPreferences共享數(shù)據(jù),需要使用SharedPreferences API讀寫數(shù)據(jù)。

而使用ContentProvider共享數(shù)據(jù)的好處是統(tǒng)一了數(shù)據(jù)訪問(wèn)方式。內(nèi)容提供者將數(shù)據(jù)封裝,只暴露出我們希望提供給其他程序的數(shù)據(jù)。內(nèi)容提供者中數(shù)據(jù)更改可被監(jiān)聽(tīng)。

使用說(shuō)明

  1. 定義類繼承ContentProvider,根據(jù)需要重寫內(nèi)部方法(增刪改查)
  2. 在清單文件的<application>節(jié)點(diǎn)下進(jìn)行配置,<provider>標(biāo)簽中需要指定name和authorities屬性
    name:類名,包名從程序Package開(kāi)始,以“.”開(kāi)始
    authorities:是訪問(wèn)Provider時(shí)的路徑,要唯一
  3. URI代表要操作的數(shù)據(jù),由scheme、authorites、path三部分組成
    content://cn.gunther.sqlite.provider/person
    scheme:固定為content,代表訪問(wèn)內(nèi)容提供者
    authorites:<provider>節(jié)點(diǎn)中的authorites屬性
    path:程序定義的路徑,可根據(jù)業(yè)務(wù)邏輯定義

示例代碼:

  1. 新建一個(gè)工程MyContentProvider,包名:com.gunther.provider。
  2. 在com.gunther.provider.dao包下新建PersonOpenHelper類繼承SQLiteOpenHelper類,該類用于創(chuàng)建數(shù)據(jù)庫(kù)。
    public class PersonOpenHelper extends SQLiteOpenHelper {

    public PersonOpenHelper(Context context, String name, CursorFactory factory, int version) {
        super(context, name, factory, version);
    }
    
    public PersonOpenHelper(Context context){
        super(context, "person.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "create table person (id integer primary key autoincrement,name varchar(20),phone varchar(20),age integer,address varchar(50));";
        db.execSQL(sql);

    }

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

    }

    }
  1. 在com.gunther.contenProvider.provider包中創(chuàng)建,PersonContentProvider類繼承ContentProvider類。同時(shí)將該P(yáng)rovider在AndroidManifest.xml中注冊(cè)。

    <provider    android:exported="true"     
    android:name="com.gunther.contenProvider.provider.PersonContentProvider"
    android:authorities="com.gunther.person" />
    
    
    
    
     public class PersonContentProvider extends ContentProvider {
     //用于存放并匹配個(gè)Uri標(biāo)識(shí)信息,一般在靜態(tài)代碼塊中對(duì)其信息進(jìn)行初始化操作
     private static UriMatcher matcher;
     //聲明一個(gè)用于操作數(shù)據(jù)庫(kù)對(duì)象
     private PersonOpenHelper openHelper;
     //主機(jī)名信息:對(duì)應(yīng)清單文件的authorities屬性
     private static final String AUTHORITY = "com.gunther.person";
     //數(shù)據(jù)庫(kù) 表名
     private static final String TABLE_PERSON_NAME = "person";
     //Uri匹配成功的返回碼
     private static final int PERSON_INSERT_CODE = 1000;
     private static final int PERSON_DELETE_CODE = 10001;
     private static final int PERSON_UPDATE_CODE = 10002;
     private static final int PERSON_QUERYALL_CODE = 10003;
     private static final int PERSON_QUERYONE_CODE = 10004;
     //靜態(tài)代碼塊,用于初始化UriMatcher
     static{
         //NO_MATCH:沒(méi)有Uri匹配的時(shí)候返回的狀態(tài)碼(-1)
         matcher = new UriMatcher(UriMatcher.NO_MATCH);
         //添加一個(gè)分機(jī)號(hào):
         //對(duì)person表進(jìn)行添加操作,如果Uri=content://com.gunther.person/person/insert,則返回PERSON_INSERT_CODE
         matcher.addURI(AUTHORITY, "person/insert", PERSON_INSERT_CODE);
         //對(duì)person表進(jìn)行刪除操作,如果Uri= content://com.gunther.person/person/delete,則返回PERSON_DELETE_CODE
         matcher.addURI(AUTHORITY, "person/delete", PERSON_DELETE_CODE);
         //對(duì)person表進(jìn)行修改操作,如果Uri= content://com.gunther.person/person/update,則返回PERSON_UPDATE_CODE
         matcher.addURI(AUTHORITY, "person/update", PERSON_UPDATE_CODE);
         //對(duì)person表進(jìn)行查詢所有操作,如果Uri= content://com.gunther.person/person,則返回PERSON_QUERYALL_CODE
         matcher.addURI(AUTHORITY, "person", PERSON_QUERYALL_CODE);
         //對(duì)person表進(jìn)行查詢單個(gè)操作,如果Uri= content://com.gunther.person/person/#,(#:代表數(shù)字)則返回PERSON_QUERYONE_CODE
         matcher.addURI(AUTHORITY, "person/#", PERSON_QUERYONE_CODE);
     }
     @Override
     public boolean onCreate() {
     //內(nèi)容提供者中,獲取contenxt,是通過(guò)getContext,與測(cè)試類一樣,不能再成員變量,構(gòu)造函數(shù)中調(diào)用,但是可以再onCreate方法中獲取。
         openHelper = new PersonOpenHelper(getContext());
         return false;
     }
     @Override
     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
         //用匹配器去匹配uri,如果匹配成功則返回匹配器中對(duì)應(yīng)的狀態(tài)碼
         int matchCode = matcher.match(uri);
         SQLiteDatabase db = openHelper.getReadableDatabase();
         switch (matchCode) {
         case PERSON_QUERYALL_CODE:
             return db.query(TABLE_PERSON_NAME, projection, selection, selectionArgs, null, null, sortOrder);
         case PERSON_QUERYONE_CODE:
     //使用ContentUris工具類解析出uri中的id
             long parseId = ContentUris.parseId(uri);
             return db.query(TABLE_PERSON_NAME, projection,"id=?", new String[]{parseId+""}, null, null, sortOrder);
         default:
             throw new IllegalArgumentException("Uri匹配失?。?+uri);
         }}
     @Override
     public Uri insert(Uri uri, ContentValues values) {
         SQLiteDatabase db = openHelper.getWritableDatabase();
         //新插入對(duì)象的id
         long id = db.insert(TABLE_PERSON_NAME, null, values);
         db.close();
         //使用ContentUris工具類將id追加到uri中,返回給客戶
         return ContentUris.withAppendedId(uri, id);
     }
    
     @Override
     public int delete(Uri uri, String selection, String[] selectionArgs) {
         SQLiteDatabase db = openHelper.getWritableDatabase();
         //返回刪除的個(gè)數(shù)
         int count = db.delete(TABLE_PERSON_NAME, selection, selectionArgs);
         //關(guān)閉數(shù)據(jù)庫(kù)
         db.close();
         return count;
     }
    
     @Override
     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
         SQLiteDatabase db = openHelper.getWritableDatabase();
         //返回更新的個(gè)數(shù)
         int count = db.update(TABLE_PERSON_NAME, values, selection, selectionArgs);
         //更新數(shù)據(jù)庫(kù)
         db.close();
         return count;
     }
    
     @Override
     public String getType(Uri uri) {
         return null;
     }
    
     }
    

?

ContentObserver

ContentObserver——內(nèi)容觀察者,目的是觀察(捕捉)特定Uri引起的數(shù)據(jù)庫(kù)的變化,繼而做一些相應(yīng)的處理,它類似于數(shù)據(jù)庫(kù)技術(shù)中的觸發(fā)器(Trigger),當(dāng)ContentObserver所觀察的Uri發(fā)生變化時(shí),便會(huì)觸發(fā)它。觸發(fā)器分為表觸發(fā)器、行觸發(fā)器,相應(yīng)地ContentObserver也分為“表“ContentObserver、“行”ContentObserver,當(dāng)然這是與它所監(jiān)聽(tīng)的Uri MIME Type有關(guān)的。

private class AppLockObserver extends ContentObserver{
    public AppLockObserver(){
        super(new Handler());
    }
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        //觀察到注冊(cè)的uri數(shù)據(jù)發(fā)送變化,根據(jù)業(yè)務(wù)需求處理
    }
}
最后編輯于
?著作權(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),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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