Android进阶知识树——ContentProvider使用和工作过程详解

前言

数据库是Android开发中最基本的数据保存方式,但由于数据库的私有性,我们无法对外提供或获取信息,当两个应用需要实现数据共享时,此时就需要本篇文章的主题——ContentProvider

1、Uri基础

在使用ContentProvider之前,先介绍下Uri基础,Uri的对于开发者来说应该并不陌生,开发中使用Uri之处有很多,如:AppLink、FileProvider等,他们的作用相同都是定位资源位置,不同的是此处定义的是数据库中的信息;

  • Uri的四个组成部分:content://contacts/people/5
  1. schema:已由Android固定设置为content://
  2. authority:ContentProvider权限,在AndroidMenifest中设置权限
  3. path:要操作的数据库表
  4. Id:查询的关键字(可选字段)
  • Uri匹配模式

Uri的匹配表示要查询的数据,对于单个数据查询,可直接使用Uri定位具体的资源位置,但当范围查询时就需要结合通配符的使用,Uri提供以下两种通配符:

  1. *:匹配由任意长度的任何有效字符组成的字符串
  2. #:匹配由任意长度的数字字符组成的字符串
content://com.example.app.provider/table2/*  //多数据查询
content://com.example.app.provider/table3/#
content://com.example.app.provider/table3/6  //单数据查询
  • Uri的转换
Uri uri = Uri.parse(“content://contacts/people/5")
  • Uri创建
//通过将 ID 值追加到 URI 末尾来访问表中的单个行
Uri singleUri = ContentUris.withAppendedId(UserDictionary.Words.CONTENT_URI,4);

2、ContentProvider使用

ContentProvider一般配合数据库共同使用,实现对外共享数据的目的,所以它需要对数据库的增删改查操作,ContentProvider也为我们提供了相应的操作方法,使用时只需实现即可,下面按照使用步骤实现一个ContentProvider:

  • 创建ContentProvider的子类,重写insert、update、query、delete、getType
  • 添加UriMatcher 映射数据表

UriMatcher的作用是在使用Uri操作数据库时,根据发起请求的Uri和配置好的uriMatcher确定本次操作的数据表

static UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH)
Static{
   
uriMatcher.addURI(AUTHORIY,”userinfo”,1)  //添加userinfo表映射
uriMatcher.addURI(AUTHORIY,”userinfo/*”,2) //*表示匹配任意长度任意字符
uriMatcher.addURI(AUTHORIY,”userinfo/#”,3)  //#匹配任意长度的的数字
}
  • insert ():添加数据
public Uri insert(Uri uri,ContentValues contentValues){
   
long newId = 0;
Uri  newUri = null;
switch (uriMatcher.match(uri)){
   
newId = dataBase.insert()  //此处的newId表示插入数据的id
newUri = Uri.parse(content://authoriy/**table/newId)
}
return newUri;
}

使用细节:

  1. dataBase添加后返回添加的id,此时使用withAppendedId ()和id创建添加的Uri
  2. insert()最终返回的是本次新添加数据的newUri
  3. 使用 ContentUris.parseId() 可以从newUri中获取本次添加数据的_ID
  • query():查询方法

ContentProvider的查询和数据库查询一样,支持条件查询和多数据查询,返回结果为查询Cursor实例

//当查询整个数据表时. Uri.parse(”content://com.book.jtm/userinfo")
dataBase.query(.)
//当查询具体一个数据. Uri.parse(”content://com.book.jtm/userinfo/123456”)
String id = uri.getPathSegments().get(1)
//调价查询时
dataBase.query(table, projection,”tel_number = ?,new String[]{
   id},null, null,sortOrder)
  • ContentObserver

提到ContentProvider的使用就会想到ContentObserver,这里一起介绍下ContentObserver,采用观察者模式在存储的数据发生修改时自动触发回调,使用起来也很简单创建ContentObserver的实例完成注册即可:

val contentObservable = object : ContentObserver(handler){
   
        override fun onChange(selfChange: Boolean, uri: Uri?) {
   
            super.onChange(selfChange, uri)
            val cursor = contentResolver.query(uri, arrayOf("_id","name"),null,null,null)
            if (cursor != null && cursor.moveToFirst()) {
   
                do {
   
                    Log.e("========", cursor.getInt(cursor.getColumnIndex("_id")).toString())
                    Log.e("========", cursor.getString(cursor.getColumnIndex("name")).toString())
                }while (cursor.moveToNext())
            }
        
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值