Android ContentObserver ContentProvider ContentResolver 綜合使用
阿新 • • 發佈:2018-12-14
1,介紹:
【1】ContentObserver——內容觀察者,目的是觀察(捕捉)特定Uri引起的資料庫的變化,做一些相應的處理,它類似於資料庫技術中的觸發器(Trigger),當ContentObserver所觀察的Uri發生變化時,便會觸發它。觸發器分為表觸發器、行觸發器,
熟悉Content Provider(內容提供者)的應該知道,我們可以通過UriMatcher類註冊不同型別的Uri,我們可以通過這些不同的
Uri來查詢不同的結果。根據Uri返回的結果。
【2】ContentObserver不是四大元件不需要在androidmanifest 註冊。
2,完成一個觀察者的小demo
1,應用1 (內容提供者)
【1】建立資料庫
public class MyOpenHelper extends SQLiteOpenHelper { /** * @param context * name :資料庫名字 * factory: 遊標工廠 * version: 資料庫的版本 */ public MyOpenHelper(Context context) { super(context, "account.db", null, 1); } //Called when the database is created for the first time. 當資料庫第一次建立的時候呼叫 那麼這個方法適合做表結構的初始化 @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table info (_id integer primary key autoincrement,name varchar(20),phone varchar(20),money varchar(20))"); db.execSQL("insert into info ('name','phone','money') values ('張三','138888','2000')"); db.execSQL("insert into info ('name','phone','money') values ('李四','139999','5000')"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
【2】AccountProvider 繼承ContentProvider 重寫方法,暴露QIUD方法。
getContext().getContentResolver().notifyChange(uri, null);方法通知內容觀察者 public class AccountProvider extends ContentProvider { // [1]定義一個urimatcher路徑匹配器 private static final UriMatcher sURIMatcher = new UriMatcher( UriMatcher.NO_MATCH); private static final int QUERYSUCESS = 0; private static final int INSERTSUCESS = 1; private static final int UPDATESUCESS = 2; private static final int DELETESUCESS = 3; private MyOpenHelper myOpenHelper; // [2]在靜態程式碼塊中新增路徑 static { /** * authority:要和你在清單檔案裡面宣告authority一樣 * * URL:統一資源定位符 https://www.baidu.com/tieba Uri:統一資源識別符號 * com.itheima.db/query uri就是自己定義的一個路徑 代表一個含義 * */ sURIMatcher.addURI("com.xiaoshuai.db", "query", QUERYSUCESS); sURIMatcher.addURI("com.xiaoshuai.db", "insert", INSERTSUCESS); sURIMatcher.addURI("com.xiaoshuai.db", "update", UPDATESUCESS); sURIMatcher.addURI("com.xiaoshuai.db", "delete", DELETESUCESS); } @Override public boolean onCreate() { myOpenHelper = new MyOpenHelper(getContext()); return false; } // 把這個方法對外暴露出去 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // [1]獲取一個匹配碼 int code = sURIMatcher.match(uri); if (code == QUERYSUCESS) { // 說明路徑匹配成功 把這個方法實現 實際上就是在這個方法對資料庫進行查詢的操作 SQLiteDatabase db = myOpenHelper.getReadableDatabase(); Cursor cursor = db.query("info", projection, selection,selectionArgs, null, null, sortOrder); //[2]當對資料庫進行查詢操作後 自己主動的傳送一條訊息 getContext().getContentResolver().notifyChange(uri, null); return cursor; } else { // 代表路徑匹配失敗 return null; // throw new IllegalArgumentException("哥們路徑不正確 ,請檢查路徑"); } } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { int code = sURIMatcher.match(uri); if (code == INSERTSUCESS) { // 代表路徑匹配成功 把insert方法實現 SQLiteDatabase db = myOpenHelper.getReadableDatabase(); // 代表新插入行的id long insert = db.insert("info", null, values); Uri uri2 = Uri.parse("com.itheima.insert/" + insert); if (insert > 0) { //[2]當對資料庫進行查詢操作後 自己主動的傳送一條訊息 getContext().getContentResolver().notifyChange(uri, null); } return uri2; } else { return null; } } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int code = sURIMatcher.match(uri); if (code == DELETESUCESS) { // 代表路徑匹配成功 把insert方法實現 SQLiteDatabase db = myOpenHelper.getReadableDatabase(); // 代表刪除的行數 int delete = db.delete("info", selection, selectionArgs); if (delete > 0) { //[2]當對資料庫進行查詢操作後 自己主動的傳送一條訊息 getContext().getContentResolver().notifyChange(uri, null); } return delete; } else { return 0; } } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int code = sURIMatcher.match(uri); if (code == UPDATESUCESS) { // 代表路徑匹配成功 把insert方法實現 SQLiteDatabase db = myOpenHelper.getReadableDatabase(); // 代表更新的行數 int update = db.update("info", values, selection, selectionArgs); if (update > 0) { //[2]當對資料庫進行查詢操作後 自己主動的傳送一條訊息 getContext().getContentResolver().notifyChange(uri, null); } return update; } else { return 0; } } }
【3】Android Manifest中宣告provider
<provider
android:authorities="com.xiaoshuai.db"
android:exported="true"
android:name=".AccountProvider" />
2,應用2 (內容解析者)
【1】獲取內容解析者,通過URI 呼叫QIUD 方法 進行操作 ContentResolver
public void click(View v) {
Log.e("Main", "我被點選了。不是我的錯");
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.xiaoshuai.db/query");
Cursor cursor = resolver.query(uri, null, null, null, null);
if (cursor != null && cursor.getCount() > 0) {
// ★★★ 想取出資料必須移動遊標
while (cursor.moveToNext()) {
String name = cursor.getString(1);
String money = cursor.getString(3);
Log.e("Main", "第二個應用~~name:" + name + "----" + money);
}
cursor.close();
}
}
//add
public void click1(View v) {
// [1]由於第一個應用的資料庫系統已經通過內容提供者暴露出來 所以可以直接通過內容解析者操作資料庫
Uri uri = Uri.parse("content://com.xiaoshuai.db/insert");
// [2]建立contentValues
ContentValues values = new ContentValues();
// 引數1 是表的列名:
values.put("name", "王五");
values.put("money", "100");
// [3]往資料庫裡面插入了一條資料
Uri insert = getContentResolver().insert(uri, values);
Log.e("Main","insert" +insert);
}
public void click2(View v) {
Uri uri = Uri.parse("content://com.xiaoshuai.db/delete");
int delete = getContentResolver().delete(uri, "name=?",
new String[] { "王五" });
Toast.makeText(getApplicationContext(), "刪除了" + delete + "行", Toast.LENGTH_LONG).show();
}
public void click3(View v) {
Uri uri = Uri.parse("content://com.xiaoshuai.db/update");
ContentValues values = new ContentValues();
values.put("money", "10000");
int update = getContentResolver().update(uri, values, "name=?",
new String[] { "王五" });
Toast.makeText(getApplicationContext(), "修改了了" + update + "行", Toast.LENGTH_SHORT)
.show();
}
}
3,應用3 (內容觀察者)
【1】 getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler())); 註冊內容觀察者進行監聽。
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]註冊內容觀察者 還是使用內容解析者去註冊
Uri uri = Uri.parse("content://com.xiaoshuai.db/");
//[2]註冊內容觀察者 引數二:如果是false 那麼第一個引數的uri必須是一個精確的uri true:可以不用是一個精確的uri
getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));
}
//定義內容觀察者
private class MyContentObserver extends ContentObserver{
public MyContentObserver(Handler handler) {
super(handler);
}
//當我們觀察的內容發生變化 這個方法就執行
@Override
public void onChange(boolean selfChange) {
System.out.println("哈哈 資料庫被人操作了");
super.onChange(selfChange);
}
}
}