Android四大應用元件之ContentProvider初探
阿新 • • 發佈:2018-12-13
理解
- 首先談一談為什麼要有ContentProvider?
當一個應用想要訪問另一個應用的資料庫時,由於每個應用的資料庫檔案時應用私有的,不能直接訪問,這時,被訪問的應用就需要一個對外的資料庫內容提供者,也就是ContentProvider。
<provider <!--自定義ContentProvider需要繼承於ContentProvider,並在功能清單檔案中註冊--> android:authorities="com.sank.ar_8_contentprovider_1_bi.personprovider" android:name=".PersonProvider" android:exported="true" />
- 什麼是ContentResolver?
ContentResolver又稱內容提供者解析類,用來解析被訪問者暴露的ContentProvider。
- 兩者之間的關聯
ContentProvider和ContentResolver之間使用URI進行通訊。
URI:
URI包含URL與URN,是一個包含請求地址的類。
主要使用的兩個工具類:
UriMatcher : 用於匹配Uri的容器
//新增一個合法的URI void addURI(String authority,String path, int code) ;
//匹配指定的uri, 返回匹配碼 int match(Uri uri);
ContentUris : 解析uri的工具類
//解析uri, 得到其中的id long parseId(Uri contentUri)
//新增id到指定的uri中 Uri withAppendedId(Uri contentUri, long id)
Demo
- ContentProvider:
- SQLite資料庫部分:
public class DBHelper extends SQLiteOpenHelper { public DBHelper(Context context) { super(context, "sank.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table person(" + "_id integer primary key autoincrement," + "name varchar(20))"); db.execSQL("insert into person " + "(name) values ('TOM')"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
- 自定義Provider類:
public class PersonProvider extends ContentProvider {
//用來存放所有的合法的uri的容器
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
//儲存一些合法的uri
//content://com.sank.ar_8_contentprovider_1_bi.personprovider/person 不根據id操作
//content://com.sank.ar_8_contentprovider_1_bi.personprovider/person/3 根據id操作
static {
matcher.addURI("com.sank.ar_8_contentprovider_1_bi.personprovider"
,"/person",1);
matcher.addURI("com.sank.ar_8_contentprovider_1_bi.personprovider"
,"/person/#",2);
}
private DBHelper dbHelper;
@Override
public boolean onCreate() {
dbHelper = new DBHelper(getContext());
return false;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection,
@Nullable String selection, @Nullable String[] selectionArgs,
@Nullable String sortOrder) {
//得到Sql連結物件
SQLiteDatabase database = dbHelper.getReadableDatabase();
//匹配uri,返回code
int code = matcher.match(uri);
if(code==1){//如何合法,進行查詢
//不根據id查詢
Cursor cursor = database.query("person", projection, selection, selectionArgs,
null, null, null);
return cursor;
}else if(code==2){
//根據id查詢
long id = ContentUris.parseId(uri);
Cursor cursor = database.query("person", projection, "_id=?", new String[]{id + ""},
null, null, null);
return cursor;
}else{
//如何不合法,丟擲異常
throw new RuntimeException("uri不合法");
}
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
return null;
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
//建立連結
SQLiteDatabase database = dbHelper.getReadableDatabase();
//匹配uri,返回code
int code = matcher.match(uri);
//檢查uri是否合法
if(code==1){
long id = database.insert("person", null, values);
//將id新增到uri中
uri = ContentUris.withAppendedId(uri,id);
database.close();
return uri;
}else{
database.close();
throw new RuntimeException("uri不合法");
}
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
//建立連結
SQLiteDatabase database = dbHelper.getReadableDatabase();
//匹配uri,返回code
int code = matcher.match(uri);
//刪除的個數
int deleteCount = -1;
//檢查uri是否合法
if(code==1){
deleteCount = database.delete("person", selection, selectionArgs);
}else if(code ==2){
long id = ContentUris.parseId(uri);
database.delete("person", "_id=" + id, null);
} else{
database.close();
throw new RuntimeException("uri不合法");
}
database.close();
return deleteCount;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
//建立資料庫連結
SQLiteDatabase database = dbHelper.getReadableDatabase();
//匹配uri
int code = matcher.match(uri);
//更新的行數
int updateCount;
//檢查是否合法
if (code == 1) {
updateCount = database.update("person", values, selection, selectionArgs);
} else if (code == 2) {
long id = ContentUris.parseId(uri);
updateCount = database.update("person", values, "_id=" + id, null);
}else {
database.close();
throw new RuntimeException("uri不合法");
}
database.close();
return updateCount;
}
}
- ContentResolver:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/*
CRUD
*/
public void insert(View view) {
//得到ContentResolver物件
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.sank.ar_8_contentprovider_1_bi.personprovider/person/");
ContentValues values = new ContentValues();
values.put("name","mary");
uri = resolver.insert(uri,values);
Toast.makeText(this,uri.toString(),Toast.LENGTH_SHORT).show();
}
public void delete(View view) {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.sank.ar_8_contentprovider_1_bi.personprovider/person/2");
int deleteCount = resolver.delete(uri,null, null);
Toast.makeText(this,"deleteCount="+deleteCount,Toast.LENGTH_SHORT).show();
}
public void update(View view) {
ContentResolver resolver = getContentResolver();
Uri uri = Uri.parse("content://com.sank.ar_8_contentprovider_1_bi.personprovider/person/1");
ContentValues values = new ContentValues();
values.put("name","Tom2");
int updateCount = resolver.update(uri, values, null, null);
Toast.makeText(this,"updateCount="+updateCount,Toast.LENGTH_SHORT).show();
}
public void query(View view) {
//得到ContentResolver物件
ContentResolver resolver = getContentResolver();
//呼叫query,得到cursor物件
Uri uri = Uri.parse("content://com.sank.ar_8_contentprovider_1_bi.personprovider/person");
Cursor cursor = resolver.query(uri, null, null, null, null);
//取出cursor中的資料
assert cursor != null;
while(cursor.moveToNext()){
int id = cursor.getInt(0);
String name = cursor.getString(1);
Toast.makeText(this,id+" : "+name,Toast.LENGTH_SHORT).show();
}
cursor.close();
}
}