- 2016年12月8日,Google中國(guó)開(kāi)發(fā)者大會(huì)在京舉行,同時(shí)正式上線了Google中國(guó)開(kāi)發(fā)者網(wǎng)站Google Developers,查看官方學(xué)習(xí)資源再也不用爬梯子了
- 簡(jiǎn)介
- 使用說(shuō)明
- 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ō)明
- 定義類繼承ContentProvider,根據(jù)需要重寫內(nèi)部方法(增刪改查)
- 在清單文件的<application>節(jié)點(diǎn)下進(jìn)行配置,<provider>標(biāo)簽中需要指定name和authorities屬性
name:類名,包名從程序Package開(kāi)始,以“.”開(kāi)始
authorities:是訪問(wèn)Provider時(shí)的路徑,要唯一 - 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ù)邏輯定義
示例代碼:
- 新建一個(gè)工程MyContentProvider,包名:com.gunther.provider。
- 在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) {
}
}
-
在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ù)需求處理
}
}