ContentProvider!

ContentProvider是Android四大組件之一。它主要的作用是:實現各個應用程序之間的(跨應用)數據共享,比如聯系人應用中就使用了ContentProvider,你在自己的應用中可以讀取和修改聯系人的數據,不過需要獲得相應的權限。
但是ContentProvider也只是起到中間人的作用,真正實現應用間數據傳輸的用SQLite。
和ContentProvider緊密祥光的就是URI!
Uri是統一標識符,代表要操作的數據,標識每一個ContentProvider,當需要的時候就通過Uri來查找對應想要的ContentProvider。從而獲取和修改等其他操作。
Android中的Uri的格式也是一下的形式,主要分為三個部分:

   A 部分:表示是一個Android內容URI,說明由ContentProvider控制數據,該部分是固定形式,不可更改的。
  ?B 部分:是URI的授權部分,是唯一標識符,用來定位ContentProvider。
     格式一般是自定義ContentProvider類的完全限定名稱,注冊時需要用到,
     如:com.alexzhou.provider.NoteProvider
  ?C 部分和D部分:是每個ContentProvider內部的路徑部分,C和D部分稱為路徑片段,C部分指向一個對象集合,
     一般用表的名字,如:/notes表示一個筆記集合;D部分指向特定的記錄,如:/notes/1表示id為1的筆記,
     如果沒有指定D部分,則返回全部記錄。
Paste_Image.png

ContentProvider可以理解為一個Android應用對外開放的接口,只要是符合它所定義的Uri格式的請求,均可以正常訪問執行操作。
其他的Android應用可以使用ContentResolver對象通過與ContentProvider同名的方法請求執行,被執行的就是ContentProvider中的同名方法。
所以ContentProvider很多對外可以訪問的方法,在ContentResolver中均有同名的方法,是一一對應的!

Paste_Image.png

ContentProvider必須要實現的幾個方法:
1、onCreate():初始化提供者。

@Override
    public boolean onCreate() {
        // TODO Auto-generated method stub
        Log.e(TAG, "onCreate");
        helper = new MySqliteHelper(getContext());
        matcher = new UriMatcher(UriMatcher.NO_MATCH);
        matcher.addURI(authority, tableName, STUDENT);
        matcher.addURI(authority, teachName, TEACHER);
        return true;
    }```
2、insert(Uri, ContentValues):插入一條數據。
3、query(Uri, String[], String, String[], String):查詢數據,返回一個數據Cursor對象。(根據括號里的參數查詢數據,后面類型的填null代表所有的數據都要查詢)

@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// TODO Auto-generated method stub
int code = matcher.match(uri);
db = helper.getReadableDatabase();
switch (code) {
case TEACHER:
Log.e(TAG, "teacher_query");
Cursor teachCursor = db.query(teachName, projection, selection,
selectionArgs, null, null, null);
return teachCursor;

    case STUDENT:
        Log.e(TAG, "teacher_query");
        Cursor cursor = db.query(tableName, projection, selection,
                selectionArgs, null, null, null);
        return cursor;
    }
    return null;
}```

4、delete(Uri, String, String[]):根據條件刪除數據。

@Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // TODO Auto-generated method stub
        
        int code=matcher.match(uri);
        db = helper.getReadableDatabase();
        switch(code){
        case TEACHER:
            Log.e(TAG, "teacher_delete");
            db.delete(teachName, selection, selectionArgs);
            break;
            
        case STUDENT:
            Log.e(TAG, "student_delete");
            db.delete(tableName, selection, selectionArgs);
            break;
        }
        return 0;
    }```

在ContentProvider的增刪改查操作中,均會傳遞一個Uri對象,通過這個對象來匹配對應的請求。那么如何確定一個Uri執行哪項操作呢?
需要用到一個UriMatcher對象,這個對象用來幫助內容提供者匹配Uri。它所提供的方法非常簡單,僅有兩個:
void addURI(String authority,String path,int code):添加一個Uri匹配項,authority為AndroidManifest.xml中注冊的ContentProvider中的authority屬性;path為一個路徑,可以設置通配符,#表示任意數字,*表示任意字符;code為自定義的一個Uri代碼。

int match(Uri uri):匹配傳遞的Uri,返回addURI()傳遞的code參數。
     在創建好一個ContentProvider之后,還需要在AndroidManifest.xml文件中對ContentProvider進行配置,使用一個<provider.../>節點,一般只需要設置兩個屬性即可訪問,一些額外的屬性就是為了設置訪問權限而存在的,后面會詳細講解:
android:name:provider的響應類。
android:authorities:Provider的唯一標識,用于Uri匹配,一般為ContentProvider類的全名。
        ContentProvider也是四大組件之一所以需要在Manifest中注冊;

在ContentProvider之前要創建一個類(MySqliteHelper)來繼承SQLiteOpenHelper這個類,其中要調用一個構造方法和兩個方法(一個創建的方法,一個更新版本的方法)。在創建的方法里要創建一個表格要用用Sql語句來完成

@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
db.execSQL("CREATE TABLE Student(id integer primary key autoincrement,name varchar(20),age varchar(10))");
db.execSQL("CREATE TABLE Teacher(id integer primary key autoincrement,tname varchar(20),tage varchar(10))");
}```

都寫好了之后,就在另一個程序內加上點擊的事件---增刪改查的點擊方法,來操作ContentProvider內寫好的對應的增刪改查

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch(v.getId()){
        case R.id.but_insert:
            ContentValues values=new ContentValues();
            values.put("tname", "老師");
            values.put("tage", "23");
            ContentValues values1=new ContentValues();
            values1.put("tname", "老師師");
            values1.put("tage", "123");
            resolver.insert(teachUri, values);
            resolver.insert(teachUri, values1);
            break;
        case R.id.but_update:
            ContentValues updateValues=new ContentValues();
            updateValues.put("tname", "李四");
            updateValues.put("tage", "32");
            resolver.update(teachUri, updateValues, "tname=?", new String[]{"老師"});
            break;
        case R.id.but_query:
            List<String> list=new ArrayList<String>();
            Cursor cursor=resolver.query(teachUri, null, null, null, null);
            while(cursor.moveToNext()){
                int nameIndex=cursor.getColumnIndex("tname");
                int ageIndex=cursor.getColumnIndex("tage");
                String nameStr=cursor.getString(nameIndex);
                String ageStr=cursor.getString(ageIndex);
                list.add(nameStr+ageStr);
            }
            ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1, list);
            lv.setAdapter(adapter);
            break;
        case R.id.but_delete:
            resolver.delete(teachUri, "tname=?", new String[]{"李四"});
            break;
        }
    }```
準備工作就是生命一個Uri、ContentResolver。

String uriStr="content://com.example.contentprovider.MyProvider/Student";
uri=Uri.parse(uriStr);

將一個字符串轉化成一個Uri格式的類型

resolver=getContentResolver();

獲取resolver的實例
通過上述操作可以實現ContentProvider應用之間的相互操作!

-----------------------------------------------------------------------------
相互學習,共同進步!
------------------------------------------------------------------------------













最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容