Android四大组件—ContentProvider详解

本文详细介绍了Android中的ContentProvider,它是四大组件之一,用于跨进程数据共享。讲解了ContentProvider的定义、工作原理、特点,以及如何自定义ContentProvider、在AndroidManifest.xml中注册、使用ContentResolver进行数据操作。同时提到了与ContentProvider相关的类如UriMatcher、ContentUris和ContentObserver的用途,最后探讨了ContentProvider的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、ContentProvider 介绍

定义

ContentProvider是Android四大组件之一,其本质上是一个标准化的数据管道,它屏蔽了底层的数据管理和服务等细节,以标准化的方式在Android 应用间共享数据、数据交互,跨进程通信。

原理

ContentProvider的底层是采用 Android中的Binder机制
具体请看文章 图文详解 Android Binder跨进程通信的原理

特点

安全,访问简单,高效,统一了数据的访问方式。

 

二、使用方法

1、自定义ContentProvider类

该类需要继承Android提供的ContentProvider基类。然后实现ContentProvide的抽象方法,实现对数据的CRUD(create,retrieve,update,delete),还有onCreate和getType。

  • onCreate(),该方法在ContentProvider创建后会被调用,当其他应用程序第一次访问ContentProvide时,该ContentProvider会被创建出来,并立即回调该onCreate方法
  • getType(Uri uri), 返回 当前Uri所代表的数据的MIME类型。如果该Uri对应数据可能包括多条记录,那么MIME类型字符串应该以 vnd.android.cursor.dir/开头;如果该Uri对应的数据只包含一条记录,那么返回MIME类型字符串应该以vnd.android.cursor.item/开头。

2、在AndroidManifest.xml中进行注册。

注册的时候,与注册广播类似。

  • 属性name指定ContentProvide实现类的类名;
  • 属性authorities是Uri标识,ContentProvide就是以这个Uri的形式对外提供数据,ContentResolve也是根据该Uri进行访问操作该应用的数据的,可以理解为网站的域名
  • 属性exported指定是否对外暴露数据,只有为true时,其他应用才可以访问该应用的数据,缺省值为true。

3、其他APK用ContentResolver对数据进行CRUD操作

通过调用Content的 getContentResolver() 方法获取 ContentResolver对象实例,其实ContentResolver的作用类似于HttpClient,获取对象后就可以根据Uri对应用的数据进行CRUD操作了。

 

三、其他相关的类

Uri

与网站https://www.oracle.com/index.html的Uri的规则类似
content://com.lzb.provide.myContentProvide:200/students 说明如下:

  • content://:协议部分,表示ContentProvider使用的协议,这个是固定的。
  • com.lzb.provide.myContentProvide:URI 的标识,也是属性authorities定义的部分,系统就是通过这个部分找到要操作那个ContentProvide,为了保证URI标识的唯一性,它一般是一个完整的、小写的类名(包.小写的类名)。
  • :200:端口号,Uri默认的端口是8080。
  • students:资源部分(资源所在的路径),访问者可以访问不同的资源,这个是动态的;如果想要访问具体那行数据,可以在后面加上该行的ID,例如上述要该路径下的第1条记录,那么Uri可以写为content://com.lzb.provide.myContentProvide/students/1。

UriMatcher

作用:在ContentProvider 中注册URI,根据 URI 匹配 ContentProvider 中对应的数据表。
该类主要提供了如下两个方法:

  • public void  addURI(String authority, String path, int code) 用于向UriMatcher注册Uri,其中参数authority与path组成一个Uri,参数code 是该Uri对应的标识码
  • public int  match(Uri uri) 根据前面注册的Uri返回其对应的标识码,如果在UriMatcher中找不到对应的Uri则返回-1。
// 步骤1:初始化UriMatcher对象
    UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); 
    //常量UriMatcher.NO_MATCH  = 不匹配任何路径的返回码
    // 即初始化时不匹配任何东西

// 步骤2:在ContentProvider 中注册URI(addURI())
    int URI_CODE_a = 1;
    int URI_CODE_b = 2;
    matcher.addURI("cn.scu.myprovider", "user1", URI_CODE_a); 
    matcher.addURI("cn.scu.myprovider", "user2", URI_CODE_b); 
    // 若URI资源路径 = content://cn.scu.myprovider/user1 ,则返回注册码URI_CODE_a
    // 若URI资源路径 = content://cn.scu.myprovider/user2 ,则返回注册码URI_CODE_b

// 步骤3:根据URI 匹配 URI_CODE,从而匹配ContentProvider中相应的资源(match())

@Override   
    public String getType(Uri uri) {   
      Uri uri = Uri.parse(" content://cn.scu.myprovider/user1");   

      switch(matcher.match(uri)){   
     // 根据URI匹配的返回码是URI_CODE_a
     // 即matcher.match(uri) == URI_CODE_a
      case URI_CODE_a:   
        return tableNameUser1;   
        // 如果根据URI匹配的返回码是URI_CODE_a,则返回ContentProvider中的名为tableNameUser1的表
      case URI_CODE_b:   
        return tableNameUser2;
        // 如果根据URI匹配的返回码是URI_CODE_b,则返回ContentProvider中的名为tableNameUser2的表
    }   
}

ContentUris

作用:操作 URI
核心方法有两个:withAppendedId()、parseId()

// withAppendedId()作用:向URI追加一个id
Uri uri = Uri.parse("content://cn.scu.myprovider/user") 
Uri resultUri = ContentUris.withAppendedId(uri, 7);  
// 最终生成后的Uri为:content://cn.scu.myprovider/user/7

// parseId()作用:从URL中获取ID
Uri uri = Uri.parse("content://cn.scu.myprovider/user/7") 
long personid = ContentUris.parseId(uri); 
//获取的结果为:7

ContentObserver

作用:观察 Uri引起 ContentProvider 中的数据变化 & 通知外界(即访问该数据访问者)
操作步骤如下:
1、注册ContentObserver 内容观察者 registerContentObserver
2、继承 ContentObserver 实现 onChange方法
3、当该URI的ContentProvider数据发生变化时,通知外界getContext().getContentResolver().notifyChange(uri, null); 
4、解除观察者 getContentResolver().unregisterContentObserver(uri)。

 

四、应用场景

为了降低上层业务对底层数据的依赖,需要增加一个数据访问层来解耦,ContentProvider充当的就是数据访问层的角色。内容提供者可以使用不同的方式来存储数据,数据可以被存放在数据库,文件,甚至是网络。

  • 可以使用自定义ContentProvider。
  • 可以使用系统自带的ContentProvider,如音频、视频、图片、通讯录和短信。
  • ContentResolver可以与ContentProvider在相同的进程间使用,但一般情况是跨进程使用。

 

参考链接
https://blog.youkuaiyun.com/lu1024188315/article/details/78303467
https://blog.youkuaiyun.com/carson_ho/article/details/76101093

更详细的的解析 https://blog.youkuaiyun.com/luoshengyang/article/details/6946067

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值