相信大家对于 Android 顶顶大名的四大组件也不陌生了。今天我们来谈一谈 ContentProvider 的用法。什么东西都是基本最重要啊,可以人是一个健忘的动物,所以需要做下来笔记,常看常新。愿我们成为真实的自己。

ContentProvider概要

从系统提供的Provider访问数据

  • 内容URI的组成
  • ContentResolve类

创建自己的Provider

  • UriMater类
  • 自定义一个Provider的步骤

ContentProvider 也有存储数据的功能,但是与安卓自带的数据库和 SharedPreferences 以及文件存储方法不同的是,后者保存下的数据只能被该应用程序使用,而前者可以让不同应用程序之间进行数据共享,它还可以选择只对哪一部分数据进行共享,从而保证程序中的隐私数据不会有泄漏风险。所以组件ContentProvider主要负责存储和共享数据。

ContentProvider有两种形式:可以使用现有的内容提供者来读取和操作相应程序中的数据,也可以创建自己的内容提供者给这个程序的数据提供外部访问接口。

2.从系统提供的Provider访问数据

既然ContentProvider有对外共享数据的功能,换句话说,其他应用程序可以通过ContentProvider对应用中的数据进行增删改查,之前学习SQLite数据存储的时候就提到过可以实现增删改查的各种辅助性方法,实际上ContentProvider是对SQLiteOpenHelper的进一步封装,不过不再用单纯的表名指明被操作的表,毕竟现在是其他程序访问它,而是用有一定格式规范的内容URI来代替。下面先来学习URI的组成。

(1)URI的组成

以之前学习数据库的demo为例,它的包名是com.example.myapplication,如果其他程序想访问该程序student.db中的student表,那么需要的内容URI如图所示:

01.png

可以看出内容 URI 可以非常清楚地表达出我们想要访问哪个程序中哪张表里的数据,但还没完,还需要将它解析成 Uri 对象才可以作为参数传入。通过调用 Uri.parse()方法,就可以将内容 URI 字符串解析成 Uri 对象了,代码如下:

02.png

Uri 这个类就是专门做这种链接转换的。其实这种链接方式和 http 很像。content:是不能变化的,后面就是包名.provider ,也是一定的,最后就是表名。

(2)ContentResolve类

现在有了酷似“表名”的Uri,类似的,在ContentResolver类中提供的一系列用于对数据进行增删改查操作的方法也酷似SQLiteDatabase的那些辅助性方法:insert()方法用于添加数据,update()方法用于更新数据,delete()方法用于删除数据,query()方法用于查询数据。它们不仅方法名一样,连提供的参数都非常相似,见下图,红色部分是区别:

03.png

所以其他程序若想要访问ContentProvider中共享的数据的方法是:

第一:通过 Context 中的 getContentResolver() 方法实例化一个 ContentResolver 对象。

第二:调用该对象的增删改查方法去操作 ContentProvider 中的数据。

下面我们来看看查询联系人数据的基本代码:

04.png

别忘记在注册文件中声明权限

不但如此,Android 6.0 之后有了运行时权限,所以我们还要加上判断才可以。

05.png

这一部分是通用代码,大家可以在使用的过程中把这部分代码封装到 BaseActivity 中去。这样可以增加代码复用。

06.png

这是需要动态申请权限的图标,不过没关系,大家记不得可以去查找一下即可。

3.创建自己的Provider

(1)UriMater类

UriMater 类有匹配内容 URI 的功能,在这里常用它的两个方法:一个是 addURI() 方法来传入 URI,它接收三个参数(权限,路径,一个自定义代码);另一个是 match() 方法用来匹配 URI,接收一个 Uri 对象,返回值是某个能够匹配这个 Uri 对象所对应的自定义代码,利用这个自定义代码,就可以判断出调用方期望访问的是哪张表中的数据了。

(2)自定义一个Provider的步骤

步骤一:新建一个类去继承ContentProvider。
步骤二:重写ContentProvider的六个抽象方法,方法及含义如图:

public class MyProvider extends ContentProvider {// 在ContentProvider 创建后调用@Overridepublic boolean onCreate() {return false;}//该方法用于提供外部应用从 ContentProvider 中获取数据@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {return null;}@Nullable@Override   //用于返回当前 Uri 代表的 MIME 类型public String getType(@NonNull Uri uri) {return null;}//该方法用于提供外部应用从 ContentProvider 中插入数据@Nullable@Overridepublic Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {return null;}//该方法用于提供外部应用从 ContentProvider 中删除数据@Overridepublic int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {return 0;}//该方法用于提供外部应用从 ContentProvider 中修改数据@Overridepublic int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {return 0;}
}

步骤三:在配置文件中进行注册,并注明属性:

android:authorities即Provider的权限,形式是包名.provider
android:name即Provider的全名,形式是包名.类名
android:exported="true"指明该Provider可被其它程序访问。

(3)例子:为student.db创建MyProvider

接下里还是给上篇的数据库demo创建一个自定义提供器MyProvider,然后在别的应用程序中通过MyProvider去操作student.db中的数据。

开始自定义提供器!一开始定义了四个常量,分别表示访问student表中的所有数据、访问student表中的单条数据(student/#用于表示student表中任意一行记录)、访问course表中的所有数据和访问course表中的单条数据。然后在静态代码块里对UriMatcher进行了初始化操作,将期望匹配的几种URI格式添加了进去。

07.png

接下来就是六个抽象方法的具体实现了,先看onCreate()方法,这里创建了一个MyHelper的实例,然后返回true表示内容提供器初始化成功,现在数据库就已经完成了创建或升级操作。

08.png

接下来是 getType()方法,需要返回一个MIME字符串。一个内容URI所对应的MIME字符串主要由三部分组分,Android对这三个部分做了以下格式规定:必须以vnd开头;如果内容URI以路径结尾,则后接android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/;最后接上vnd.< authority>.< path>。所以四个内容URI对应的MIME字符串分别是:

09.png

在query()方法里先获取到SQLiteDatabase的实例,然后根据传入的Uri参数判断出用户想要访问哪张表,再调用SQLiteDatabase的query()进行查询并将Cursor对象返回就好了。注意当访问的是单条数据时调用了Uri对象的getPathSegments()方法,它会将内容URI权限之后的部分以“/”符号进行分割,并把分割后的结果放入到一个字符串列表中,那这个列表的第0个位置存放的就是路径,第1个位置存放的就是id了。得到了id之后,再通过selection和selectionArgs参数进行约束,就实现了查询单条数据的功能。

补充部分:事务有关:
事务是恢复和并发控制的基本单位。

事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性

原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。


/*** SQLite的事务管理*/public void transation() {SQLiteDatabase db = helper.getWritableDatabase();// 事务开始db.beginTransaction();//事务的处理try {db.execSQL("update person set age = age-1 where name = 'xiaohong'");db.execSQL("update person set age = age+1 where name = 'xiaolan'");//事务处理成功db.setTransactionSuccessful();} finally {//结束事务db.endTransaction();}}

当使用 sqlite 数据库批量插入数据的时候使用事务就可以提升效率。

在使用 sqlite 数据库的时候有那些可以优化的地方。

一:显示使用事务
Android中,无论是使用SQLiteDatabase的insert,delete等方法还是execSQL都开启了事务,来确保每一次操作都具有原子性,使得结果要么是操作之后的正确结果,要么是操作之前的结果。所以我们可以显示的支持事务,这样事务的操作打开次数会明显变少。

二:建立索引
创建索引的基本语法:

CREATE INDEX index_name ON table_name;

三:及时关闭Cursor

四:耗时异步化
数据库的操作,属于本地IO,通常比较耗时,如果处理不好,很容易导致ANR,因此建议将这些耗时操作放入异步线程中处理。

今天状态不够好,前途漫漫不知路在何方。只能一步一步向前走。
愿我们成为真实的自己。

我要做 Android 之 ContentProvider相关推荐

  1. 009 Android之ContentProvider

    文章目录 Android文件权限简述 ContentProvider 内容提供者 ContentResolver URI 什么是URI URI示例 URI和URL ContentProvider实例 ...

  2. provider android简书,Android 使用ContentProvider在应用间共享数据

    Android 使用ContentProvider在应用间共享数据 题图 www.gratisography.com 在开发的过程中,有时会有需求要实现应用程序之间实现数据共享,在Android系统中 ...

  3. Android之ContentProvider数据存储

    一.ContentProvider保存数据介绍 一个程序可以通过实现一个ContentProvider的抽象接口将自己的数据完全暴露出去,而且ContentProvider是以类似数据库中表的方式将数 ...

  4. Android About ContentProvider

    Contents: ContentProvider Structural Analysis What is URI? Query Attribute,SQL UNION   ContentProvid ...

  5. Android之ContentProvider

    文章目录 简介 ContentResolver.ContentProvider和URI Uri简介 Uri处理 自定义ContentProvider 1. 新建类继承ContentProvider 2 ...

  6. android使用ContentProvider初始化sdk,初始化时机

    文章目录 系列目录 前言 什么是ContentProvider sdk初始化 常规初始化方案 使用ContentProvider初始化sdk 为什么ContentProvider可以作为sdk初始化 ...

  7. Android【ContentProvider案例】

    ContentProvider实现跨程序数据共享,实例如下: 数据库基于数据存储中的使用的数据库,点击Here 1]ContentProvider类 public class ContentProvi ...

  8. android中contentProvider及ContentResolver

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程 这个技术是解决应用之间的一个调用,如常见的应用间数据库查询,内容提供者暴露接口,内容解析器Conten ...

  9. android 53 ContentProvider内容提供者

    ContentProvider内容提供者:像是一个中间件一样,一个媒介一样,可以以标准的增删改差操作对手机的文件.数据库进行增删改差.通过ContentProvider查找sd卡的音频文件,可以提供标 ...

最新文章

  1. CrackMe_001
  2. 【漫画】以后在有面试官问你AVL树,你就把这篇文章扔给他。
  3. 营销增长大揭密丨市场人应具备的101种硬核营销姿势
  4. pythorch学习笔记
  5. 虚拟机vmware11装Mac ox 10.8 解决windows8.1下unlocker202 vmxsmc.exe已停止工作的问题
  6. 将Myeclipse非maven项目,导入到IDEA
  7. linux+PATH
  8. scala学习-11-package object
  9. HDOJ-1050-Moving Tables(nyoj220)
  10. 5.Git使用详细教程
  11. 基于Java的简单WebAPI接口调用(中国气象数据网接口调用示例)
  12. 直流电机正反转驱动电路板
  13. Android 高德地图自定义InfoWindow
  14. java毕业设计药品管理系统Mybatis+系统+数据库+调试部署
  15. 助力Java初级程序员快速成长的营养书单
  16. 聚合物电容作用原理与基础
  17. 我不是刘德华-新地/卢克
  18. 微信公众平台针对欺诈等违规行为处理结果公示
  19. 阿里云培训-AS(弹性伸缩)
  20. c语言入门---函数

热门文章

  1. 如何反映两条曲线的拟合精度_中走丝线切割机床的加工精度用什么来衡量
  2. C语言之文件读写探究(二):fputc、fgetc、feof(一次读写一个字符(文本操作))
  3. C++之指针探究(十四):回调函数
  4. __clone class php_「PHP 技巧」 不要直接克隆对象,请使用深拷贝
  5. 模拟黑洞图像_黑洞“真容”今晚将被公布,先马约你一起见证~
  6. 图片变色_一张图看懂手机CMF史,附带手机渐变色工艺解析
  7. orb特征 稠密特征_一种基于ORB-SLAM2的双目三维稠密建图方法技术
  8. mysql5.0 mac_Mac OS X下MySQL 5.0的默认连接数
  9. feign扫描_微服务通信之feign的注册、发现过程
  10. java304是什么错误_304 Not Modified 的意思 (Web的Cache问题)