Android ContentProvider内容提供者的详解

前面我们已经对四大组件的三个有了一定程度的了解,接下来我们来了解四大组件的最后一个——ContentProvider(内容提供者)。相比较前面的三个,内容提供者在日常的开发过程中用到的比较少,但是这并不意味着它不重要,所以接下来我们就来一起来揭开它神秘的面纱吧。

我们知道在Android中,大部分的数据都是在应用内自己运作的,即应用的数据大部分都是私有的,那么,假设我需要将自己应用内的数据暴露给其他的APP或者说我需要获取系统上的其他应用的数据该怎么办呢?这个时候ContentProvider就派上用场了。

ContentProvider的主要作用就是解决应用之间数据共享的问题,包括获取系统内置的APP(比如联系人)和那些暴露接口的APP,那么ContentProvider到底是怎么运作的呢?在讲解ContentProvider之前,我们先来了解一下几个比较重要的概念。

概念一:URI(统一资源标识符)

我们通常在获取后端数据的时候,都会传递一个URL地址,通常的写法是
http://www.xxxx.com/web/
然后在此基础上传递参数,通过这样的方式就能拿到我们想要的数据,大家难道都不会好奇为什么就靠这样一行简单的代码就可以拿到我们想要的数据啦,其实大家了解网络这一块的话就会知道,网络上的所有东西,包括网页、文本、图片、音频、视频其实都是有一个地址的,类似于我们的身份证,具有唯一性,每当我们发出一个这样的请求时,系统就会根据我们给的地址去找到对应的资源文件并进行返回,由于地址具有唯一性,所以我们可以正确的拿到准确的数据。那么对于那些手机上的那些资源文件,我们又怎么拿到想要的数据呢?这个时候URI就能派上用场了。那么什么是URI呢?它和URL又有什么区别呢?

URI包括URL和URN两个类别,URL是URI的子集,所以URL一定是URI,而URI不一定是URL。
URI = Uniform Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。
URL = Uniform Resource Locator 统一资源定位符,一种定位资源的主要访问机制的字符串,一个标准的URL必须包括:protocol、host、port、path、parameter、anchor。
URN = Uniform Resource Name 统一资源名称,通过特定命名空间中的唯一名称或ID来标识资源。

当然在Android开发中,我们经常使用的并不是URI而是Uri,那么这个Uri又是什么呢?它和URI有什么区别呢?

1.所属的包不同。URI位置在java.net.URI,显然是Java提供的一个类。而Uri位置在android.net.Uri,是由Android提供的一个类。所以初步可以判断,Uri是URI的“扩展”以适应Android系统的需要。

2.作用的不同。URI类代表了一个URI(这个URI不是类,而是其本来的意义:通用资源标志符——Uniform Resource Identifier)实例。Uri类是一个不可改变的URI引用,包括一个URI和一些碎片,URI跟在“#”后面。建立并且转换URI引用。而且Uri类对无效的行为不敏感,对于无效的输入没有定义相应的行为,如果没有另外制定,它将返回垃圾而不是抛出一个异常。

简单来说,Uri是Android开发的,扩展了Java中URI的一些功能来特定的适用于Android开发,所以大家在开发时,只使用Android 提供的Uri即可。那么我们来看看Uri的组成结构是什么样子的。

Uri结构:<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]

Scheme:Uri的模式,比如http、file、content。如果Uri中没有指定scheme,意味着Uri无效。

Host:Uri的主机名,比如www.baidu.com。如果Uri中没有指定host,意味着Uri无效。

Port:Uri的端口号,比如8080,仅在scheme和host指定的情况下才有意义。

Path、pathPrefix、pathPattern表示路径信息。Path对应的是完整的路径信息;pathPattern也表示的是完整的路径信息,但是允许其中包含通配符。pathPrefix表示路径的前缀信息。

概念二:UriMatch

主要用于匹配Uri.这里的匹配是发生在ContentProvider中的,假如我们向ContentProvider中插入一条数据,不可能为所欲为的想怎么干就怎么干,在ContentProvider肯定要做一个判断,只有在符合条件下才会去执行你想要执行的操作,这里的判断就是用UriMatch进行匹配。主要的方法有两个:

(1)UriMatch.addURI(String authority, String path, int code)
在ContentProvider添加一个用于匹配的Uri,当匹配成功时返回code。Uri可以是精确的字符串,Uri中带有*表示可匹配任意text,#表示只能匹配数字。

(2)UriMatch.match(Uri uri)
对传递过来的uri进行验证,查看是否匹配成功。

概念三:ContentResolver

主要用于对ContentProvider中的数据进行增删改查的操作,其主要的方法有:

1)public Uri insert(Uri uri, ContentValues values)
该方法用于往ContentProvider添加数据。

2)public int delete(Uri uri, String selection, String[] selectionArgs)
该方法用于从ContentProvider删除数据。

3)public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
该方法用于更新ContentProvider中的数据。

4)public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
该方法用于从ContentProvider中获取数据。

这四个方法中每个方法的参数所代表的意思是:

(1)Uri uri:指定查询某个应用程序下的某一张表(注意,ContentProvider对外提供的数据更多是以数据库表的形式展现的)
(2)String[] projection:指定查询的列名
(3)ContentValues values:SQLite数据库操作的辅助类
(4)String selection:指定where的约束条件
(5)String[] selectionArgs:为where中的占位符提供具体的值
(6)String sortOrder:指定查询结果的排序方式

概念四:ContentProvider中getType()方法

getType()是所有的内容提供者都必须提供的一个方法,用于获取Uri对象所对应的MIME类型,一个内容URI所对应的MIME字符串主要由3部分组成,Android对这3个部分做了如下格式规定:
(1)必须以vnd开头。
(2)如果内容URI以路径结尾,则后接android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/。
(3)最后接上vnd.authority.path

讲完了这些重要的概念,接下来我们就来自己创建一个内容提供器。

第一步:创建数据库以及对应的表

/**
 * author: zhoufan
 * data: 2021/6/18 16:42
 * content:
 */
class MyDatabaseHelper(
    context: Context?,
    name: String?,
    factory: SQLiteDatabase.CursorFactory?,
    version: Int
) : SQLiteOpenHelper(context, name, factory, version) {
   

    private var mContext: Context? = null

    init {
   
        mContext = context
    }

    // 创建SQL语句
    var CREATE_BOOK =
        "create table Book (" + "id integer primary key autoincrement, " + "author text, " + "price real, " + "pages integer," + "name text)"
    var CREATE_CATEGORY =
        "create table Category (" + "id integer primary key autoincrement, " + "category_name text, " + "category_code integer)"

    override fun onCreate(db: SQLiteDatabase?) {
   
        db?.execSQL(CREATE_BOOK)
        db?.execSQL(CREATE_CATEGORY)
        Toast.makeText(mContext, "Create succeeded"</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值