Android開發(fā):ContentProvider實例詳解

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

簡介

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ù)和存儲數(shù)據(jù)的方法瑰步,就可以向其他應(yīng)用共享其數(shù)據(jù)矢洲。

雖然使用其他方法也可以對外共享數(shù)據(jù),但數(shù)據(jù)訪問方式會因數(shù)據(jù)存儲的方式而不同缩焦,如:采用文件方式對外共享數(shù)據(jù)读虏,需要進(jìn)行文件操作讀寫數(shù)據(jù);采用SharedPreferences共享數(shù)據(jù)舌界,需要使用SharedPreferences API讀寫數(shù)據(jù)掘譬。

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

使用說明

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

示例代碼:

  1. 新建一個工程MyContentProvider他托,包名:com.gunther.provider掖肋。
  2. 在com.gunther.provider.dao包下新建PersonOpenHelper類繼承SQLiteOpenHelper類,該類用于創(chuàng)建數(shù)據(jù)庫赏参。
    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類。同時將該P(yáng)rovider在AndroidManifest.xml中注冊把篓。

    <provider    android:exported="true"     
    android:name="com.gunther.contenProvider.provider.PersonContentProvider"
    android:authorities="com.gunther.person" />
    
    
    
    
     public class PersonContentProvider extends ContentProvider {
     //用于存放并匹配個Uri標(biāo)識信息纫溃,一般在靜態(tài)代碼塊中對其信息進(jìn)行初始化操作
     private static UriMatcher matcher;
     //聲明一個用于操作數(shù)據(jù)庫對象
     private PersonOpenHelper openHelper;
     //主機(jī)名信息:對應(yīng)清單文件的authorities屬性
     private static final String AUTHORITY = "com.gunther.person";
     //數(shù)據(jù)庫 表名
     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:沒有Uri匹配的時候返回的狀態(tài)碼(-1)
         matcher = new UriMatcher(UriMatcher.NO_MATCH);
         //添加一個分機(jī)號:
         //對person表進(jìn)行添加操作韧掩,如果Uri=content://com.gunther.person/person/insert,則返回PERSON_INSERT_CODE
         matcher.addURI(AUTHORITY, "person/insert", PERSON_INSERT_CODE);
         //對person表進(jìn)行刪除操作,如果Uri= content://com.gunther.person/person/delete,則返回PERSON_DELETE_CODE
         matcher.addURI(AUTHORITY, "person/delete", PERSON_DELETE_CODE);
         //對person表進(jìn)行修改操作,如果Uri= content://com.gunther.person/person/update,則返回PERSON_UPDATE_CODE
         matcher.addURI(AUTHORITY, "person/update", PERSON_UPDATE_CODE);
         //對person表進(jìn)行查詢所有操作,如果Uri= content://com.gunther.person/person,則返回PERSON_QUERYALL_CODE
         matcher.addURI(AUTHORITY, "person", PERSON_QUERYALL_CODE);
         //對person表進(jìn)行查詢單個操作,如果Uri= content://com.gunther.person/person/#,(#:代表數(shù)字)則返回PERSON_QUERYONE_CODE
         matcher.addURI(AUTHORITY, "person/#", PERSON_QUERYONE_CODE);
     }
     @Override
     public boolean onCreate() {
     //內(nèi)容提供者中紊浩,獲取contenxt,是通過getContext,與測試類一樣郎楼,不能再成員變量万伤,構(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敌买,如果匹配成功則返回匹配器中對應(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();
         //新插入對象的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();
         //返回刪除的個數(shù)
         int count = db.delete(TABLE_PERSON_NAME, selection, selectionArgs);
         //關(guān)閉數(shù)據(jù)庫
         db.close();
         return count;
     }
    
     @Override
     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
         SQLiteDatabase db = openHelper.getWritableDatabase();
         //返回更新的個數(shù)
         int count = db.update(TABLE_PERSON_NAME, values, selection, selectionArgs);
         //更新數(shù)據(jù)庫
         db.close();
         return count;
     }
    
     @Override
     public String getType(Uri uri) {
         return null;
     }
    
     }
    

?

ContentObserver

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

private class AppLockObserver extends ContentObserver{
    public AppLockObserver(){
        super(new Handler());
    }
    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        //觀察到注冊的uri數(shù)據(jù)發(fā)送變化臼疫,根據(jù)業(yè)務(wù)需求處理
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末择份,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子烫堤,更是在濱河造成了極大的恐慌荣赶,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸽斟,死亡現(xiàn)場離奇詭異拔创,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)湾盗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門伏蚊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人格粪,你說我怎么就攤上這事躏吊。” “怎么了帐萎?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵比伏,是天一觀的道長。 經(jīng)常有香客問我疆导,道長赁项,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮悠菜,結(jié)果婚禮上舰攒,老公的妹妹穿的比我還像新娘。我一直安慰自己悔醋,他們只是感情好摩窃,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芬骄,像睡著了一般猾愿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上账阻,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天蒂秘,我揣著相機(jī)與錄音,去河邊找鬼淘太。 笑死姻僧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的琴儿。 我是一名探鬼主播段化,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼造成!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起雄嚣,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤晒屎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后缓升,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鼓鲁,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年港谊,在試婚紗的時候發(fā)現(xiàn)自己被綠了骇吭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡歧寺,死狀恐怖燥狰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情斜筐,我是刑警寧澤龙致,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站顷链,受9級特大地震影響目代,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一榛了、第九天 我趴在偏房一處隱蔽的房頂上張望在讶。 院中可真熱鬧,春花似錦霜大、人聲如沸真朗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽遮婶。三九已至,卻和暖如春湖笨,著一層夾襖步出監(jiān)牢的瞬間旗扑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工慈省, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留臀防,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓边败,卻偏偏與公主長得像袱衷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子笑窜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容