什么是ContentProvider?
ContentProvider是Android4大组件之一,我们平时使用的机会可能比较少。其底层通过Binder进行数据共享。如果我们要对第三方应用提供数据,可以考虑使用ContentProvider实现。
如何使用
与其他的ContentProvider通信。
要实现与其他的ContentProvider通信首先要查找到对应的ContentProvider进行匹配。android中ContenProvider借助ContentResolver通过Uri与其他的ContentProvider进行匹配通信。
认识Uri 来自:https://www.cnblogs.com/tgyf/p/4696288.html
URI为系统中的每一个资源赋予一个名字,比方说通话记录。每一个ContentProvider都拥有一个公共的URI,用于表示ContentProvider所提供的数据。 Android所提供的ContentProvider都位于android.provider包中, 可以将URI分为A、B、C、D 4个部分来理解。如对于content://com.wang.provider.myprovider/tablename/id:
a、标准前缀——content://,用来说明一个Content Provider控制这些数据;
b、URI的标识——com.wang.provider.myprovider,用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。对于第三方应用程序,为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。这个标识在元素的authorities属性中说明,一般是定义该ContentProvider的包.类的名称;
c、路径——tablename,通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了;
d、记录ID——id,如果URI中包含表示需要获取的记录的ID,则返回该id对应的数据,如果没有ID,就表示返回全部;
对于第三部分路径(path)做进一步的解释,用来表示要操作的数据,构建时应根据实际项目需求而定。如:
a、操作tablename表中id为11的记录,构建路径:/tablename/11;
b、操作tablename表中id为11的记录的name字段:tablename/11/name;
c、操作tablename表中的所有记录:/tablename;
d、操作来自文件、xml或网络等其他存储方式的数据,如要操作xml文件中tablename节点下name字段:/ tablename/name;
e、若需要将一个字符串转换成Uri,可以使用Uri类中的parse()方法,如:
Uri uri = Uri.parse("content://com.wang.provider.myprovider/tablename");
最简单的查询ContentProvider
- 通过Context获取ContentResolver
- 调用它的query方法
ContentResolver resolver = getContentResolver();
Cursor cursor = resolver.query(Uri.parse(""),null,null,null,null);
if(cursor != null){
while (cursor.moveToNext()){
Log.d("tag","query result "+cursor.getColumnNames());
}
cursor.close();
}
实现自己的ContentProvider
实现自的ContentProvider需要继承Android系统的ContentProvider然后实现下面的几个方法。
- onCreate()
- query()
- getType()
- insert()
- delete()
- update()
需要注意的是除了onCreate()其他的方法都运行在binder线程池。
然后在Manifest中声明对应的contentProvider即可。
contentProvider实现
class DataContentProvider : ContentProvider() {
private val tag = "DataContentProvider"
private var dbHelper:DBHelper? = null
override fun insert(uri: Uri, values: ContentValues?): Uri? {
return uri
}
override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?): Cursor? {
val cursor = dbHelper?.readableDatabase?.query(DBHelper.USER_TABLE_NAME,projection,null,selectionArgs,null,null,sortOrder)
Log.d(tag,"call query cursor is $cursor")
return cursor
}
override fun onCreate(): Boolean {
dbHelper = DBHelper(this.context)
val db = dbHelper?.writableDatabase
db?.execSQL("delete from ${
DBHelper.USER_TABLE_NAME}");
db?.execSQL("insert into ${
DBHelper.USER_TABLE_NAME} values(1,'XW');")
db?.execSQL("insert into ${
DBHelper.USER_TABLE_NAME} values(2,'XZ');")
return true
}
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<String>?): Int {
return 0
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<String>?): Int {
return 0
}
override fun getType(uri: Uri): String? {
return null
}
}
class DBHelper //数据库版本号
(context: Context?) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
override fun onCreate(db: SQLiteDatabase) {
// 创建两个表格:用户表 和职业表
db.execSQL("CREATE TABLE IF NOT EXISTS $USER_TABLE_NAME(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)")
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
}
companion object {
// 数据库名
private const val DATABASE_NAME = "demo_provider.db"
// 表名
const val USER_TABLE_NAME = "user"
private const val DATABASE_VERSION = 1
}
}
Manifest注册如下:
<provider
android:name=".contentprovider.DataContentProvider"
android:authorities="com.txl.demo.content.provider"