1. 程式人生 > >Android ContentObserver ContentProvider ContentResolver 綜合使用

Android ContentObserver ContentProvider ContentResolver 綜合使用

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);

        }

    }

}