理解
- 首先谈一谈为什么要有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();
}
}