ContentProvider是Android四大組件之一。它主要的作用是:實(shí)現(xiàn)各個(gè)應(yīng)用程序之間的(跨應(yīng)用)數(shù)據(jù)共享,比如聯(lián)系人應(yīng)用中就使用了ContentProvider,你在自己的應(yīng)用中可以讀取和修改聯(lián)系人的數(shù)據(jù),不過需要獲得相應(yīng)的權(quán)限。
但是ContentProvider也只是起到中間人的作用,真正實(shí)現(xiàn)應(yīng)用間數(shù)據(jù)傳輸?shù)挠肧QLite。
和ContentProvider緊密祥光的就是URI!
Uri是統(tǒng)一標(biāo)識符,代表要操作的數(shù)據(jù),標(biāo)識每一個(gè)ContentProvider,當(dāng)需要的時(shí)候就通過Uri來查找對應(yīng)想要的ContentProvider。從而獲取和修改等其他操作。
Android中的Uri的格式也是一下的形式,主要分為三個(gè)部分:
A 部分:表示是一個(gè)Android內(nèi)容URI,說明由ContentProvider控制數(shù)據(jù),該部分是固定形式,不可更改的。
?B 部分:是URI的授權(quán)部分,是唯一標(biāo)識符,用來定位ContentProvider。
格式一般是自定義ContentProvider類的完全限定名稱,注冊時(shí)需要用到,
如:com.alexzhou.provider.NoteProvider
?C 部分和D部分:是每個(gè)ContentProvider內(nèi)部的路徑部分,C和D部分稱為路徑片段,C部分指向一個(gè)對象集合,
一般用表的名字,如:/notes表示一個(gè)筆記集合;D部分指向特定的記錄,如:/notes/1表示id為1的筆記,
如果沒有指定D部分,則返回全部記錄。
ContentProvider可以理解為一個(gè)Android應(yīng)用對外開放的接口,只要是符合它所定義的Uri格式的請求,均可以正常訪問執(zhí)行操作。
其他的Android應(yīng)用可以使用ContentResolver對象通過與ContentProvider同名的方法請求執(zhí)行,被執(zhí)行的就是ContentProvider中的同名方法。
所以ContentProvider很多對外可以訪問的方法,在ContentResolver中均有同名的方法,是一一對應(yīng)的!
ContentProvider必須要實(shí)現(xiàn)的幾個(gè)方法:
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):插入一條數(shù)據(jù)。
3、query(Uri, String[], String, String[], String):查詢數(shù)據(jù),返回一個(gè)數(shù)據(jù)Cursor對象。(根據(jù)括號里的參數(shù)查詢數(shù)據(jù),后面類型的填null代表所有的數(shù)據(jù)都要查詢)
@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[]):根據(jù)條件刪除數(shù)據(jù)。
@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的增刪改查操作中,均會傳遞一個(gè)Uri對象,通過這個(gè)對象來匹配對應(yīng)的請求。那么如何確定一個(gè)Uri執(zhí)行哪項(xiàng)操作呢?
需要用到一個(gè)UriMatcher對象,這個(gè)對象用來幫助內(nèi)容提供者匹配Uri。它所提供的方法非常簡單,僅有兩個(gè):
void addURI(String authority,String path,int code):添加一個(gè)Uri匹配項(xiàng),authority為AndroidManifest.xml中注冊的ContentProvider中的authority屬性;path為一個(gè)路徑,可以設(shè)置通配符,#表示任意數(shù)字,*表示任意字符;code為自定義的一個(gè)Uri代碼。
int match(Uri uri):匹配傳遞的Uri,返回addURI()傳遞的code參數(shù)。
在創(chuàng)建好一個(gè)ContentProvider之后,還需要在AndroidManifest.xml文件中對ContentProvider進(jìn)行配置,使用一個(gè)<provider.../>節(jié)點(diǎn),一般只需要設(shè)置兩個(gè)屬性即可訪問,一些額外的屬性就是為了設(shè)置訪問權(quán)限而存在的,后面會詳細(xì)講解:
android:name:provider的響應(yīng)類。
android:authorities:Provider的唯一標(biāo)識,用于Uri匹配,一般為ContentProvider類的全名。
ContentProvider也是四大組件之一所以需要在Manifest中注冊;
在ContentProvider之前要?jiǎng)?chuàng)建一個(gè)類(MySqliteHelper)來繼承SQLiteOpenHelper這個(gè)類,其中要調(diào)用一個(gè)構(gòu)造方法和兩個(gè)方法(一個(gè)創(chuàng)建的方法,一個(gè)更新版本的方法)。在創(chuàng)建的方法里要?jiǎng)?chuàng)建一個(gè)表格要用用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))");
}```
都寫好了之后,就在另一個(gè)程序內(nèi)加上點(diǎn)擊的事件---增刪改查的點(diǎn)擊方法,來操作ContentProvider內(nèi)寫好的對應(yīng)的增刪改查
@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;
}
}```
準(zhǔn)備工作就是生命一個(gè)Uri、ContentResolver。
String uriStr="content://com.example.contentprovider.MyProvider/Student";
uri=Uri.parse(uriStr);
將一個(gè)字符串轉(zhuǎn)化成一個(gè)Uri格式的類型
resolver=getContentResolver();
獲取resolver的實(shí)例
通過上述操作可以實(shí)現(xiàn)ContentProvider應(yīng)用之間的相互操作!
-----------------------------------------------------------------------------
相互學(xué)習(xí),共同進(jìn)步!
------------------------------------------------------------------------------