Android 基础总结(七)ContentProvider

Android 开发的四大组件分别是:活动(activity),用于表现功能;服务(service),后台运行服务,不提供界面呈现;广播接受者(Broadcast Receive),用于接收广播;内容提供者(Content Provider),支持多个应用中存储和读取数据,相当于数据库。

一 概述

1.1 什么是ContentProvider

ContentProvider即内容提供者,是Android四大组件之一,是一种共享型组件。
ContentProvider为不同的应用之间实现数据共享,提供统一的接口,也就是说ContentProvider可以实现进程间的数据共享,实现跨进程通信。

ContentProvider通过Uri来唯一标识ContentProvider & 其中的数据,通过ContentProvider.getType(uri)来返回MIME类型数据。通过ContentResolver的增删改查方法实现对共享数据的操作,还可以通过注册ContentObserver来监听数据是否发生了变化来对应的刷新界面。

注意:ContentProvider 的作用不是实现进程间通信,它只是为进程间通信提供了一套统一接口,真正实现进程间通信的是底层的 Binder 机制。
优点:使用 ContentProvider 允许应用透明地将数据开放给其它应用,无论底层数据采用何种实现方式(网络、内存、文件或数据库),外界对于数据的访问方式都是统一的 & 固定的。外界只关心采用 CURD 来访问 ContentProvider 的数据,至于其内部数据的实现是采用文件存储还是数据库存储,外界是不感知的。

1.2 统一资源标识符(URI)

统一资源标识符(Uniform Resource Indentifier)的作用是 唯一标识 ContentProvider 的数据。在通过 ContentResolver 解析数据时,URI 是必要的参数。
URI 遵循固定的格式,一共分为四个部分:schema://authority/path/id

元素描述
schema(方案)URI的前缀,固定为 content://
authority(权威)标识 ContentProvider 的唯一字符串,对应于注册时指定的 android:authority 属性
path(路径)ContentProvider中数据表的表名。标识 authority 数据的某些子集
id(记录 id)标识 path 子集中的某个记录(不指定是标识全部记录)数据表中数据的标识

1.3 MIME数据类型

MIME用于指定某个扩展名的文件用某种应用程序打开,如指定.html文件采用text应用程序打开,指定.pdf文件用flash应用程序打开。
一个 MIME 类型分为「主类型」+「子类型」,例如 .html 文件对应的 MIME 类型为 text/html,其中 text 为主类型,html 为子类型。

在 ContentProvider 中,通过 getType(Uri) 方法来确定 URI 对应的 MIME 类型,返回值可以返回 标准 MIME 类型或者自定义 MIME 类型,这是一个抽象方法,需要由子类实现:

public abstract String getType(Uri uri);

标准 MIME 类型
标准 MIME 类型中常见的主类型有:
声音:audio
视频:video
图像:image
文本:text

对应的 MIMIE 类型举例:

扩展名MIME
.htmltext/html
.txttext/plain
.pngimage/png
.jpegimage/jpeg

二 ContentProvider核心类

Android提供了3个用于辅助ContentProvider的工具类:ContentUris、UriMatcher和ContentObserver

2.1 ContentUris

ContentUris 是 Uri 的工具类,在 ContentUris 的文档注释中主要描述了 ContentProvider URI 所遵循的格式,此外 ContentUris 还提供了三个工具方法:

1、从 Uri 中解析主键 id
public static long parseId(Uri contentUri) {
    String last = contentUri.getLastPathSegment();
    return last == null ? -1 : Long.parseLong(last);
}

2、向 Uri 追加一个 id
public static Uri.Builder appendId(Uri.Builder builder, long id) {
    return builder.appendEncodedPath(String.valueOf(id));
}

3、向 Uri 追加一个 id
public static Uri withAppendedId(Uri contentUri, long id) {
    return appendId(contentUri.buildUpon(), id).build();
}

2.2 UriMatcher

UriMatcher类是一个工具类,帮助匹配ContentProvider中的Uri。只提供了两个方法——addURI和match方法。

    private final static String AUTHORITY = "com.android.peter.provider";
    private final static int STUDENT_URI_CODE = 0;
    private final static UriMatcher sUriMatcher;

    static {
        sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        //把Uri和Uri_Code相关联
        sUriMatcher.addURI(AUTHORITY,"student",STUDENT_URI_CODE);
    }
    //通过match方法能够根据传递的uri匹配到对应的Uri_Code
    int uriType = sUriMatcher.match(uri);

2.3 ContentObserver

ContentObserver内容观察者,用于观察Uri引起ContentProvider中数据变化 & 通知外界(即访问该数据访问者)。当ContentProvider中的数据发生变化时,就会触发该ContentObserver类。其具体使用如下:

// 步骤1:注册内容观察者ContentObserver
    getContentResolver().registerContentObserver(uri);
    // 通过ContentResolver类进行注册,并指定需要观察的URI

// 步骤2:当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
    public class UserContentProvider extends ContentProvider { 
      public Uri insert(Uri uri, ContentValues values) { 
      db.insert("user", "userid", values); 
      getContext().getContentResolver().notifyChange(uri, null); 
      // 通知访问者
   } 
}

// 步骤3:解除观察者
 getContentResolver().unregisterContentObserver(uri);
    // 同样需要通过ContentResolver类进行解除

2.4 ContentResolver类

用于管理不同的ContentProvider间的操作,即通过URI即可操作不同的ContentProvider中的数据,外部进程通过ContentResolver类从而与ContentProvider类进行交互。
一般来说,一款应用要使用多个ContentProvider,若需要了解每个ContentProvider的不同实现从而完成数据交互,操作成本高、难度大。因此需要在ContentProvider上多加一个ContentResolver来进行统一管理。

ContentResolver类提供了与ContentProvider类相同名 & 作用的4个方法:

// 外部进程向 ContentProvider 中添加数据
public Uri insert(Uri uri, ContentValues values)  

// 外部进程删除 ContentProvider 中的数据
public int delete(Uri uri, String selection, String[] selectionArgs)

// 外部进程更新 ContentProvider 中的数据
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)  

// 外部应用 获取 ContentProvider 中的数据
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

三 ContentProvider的使用

3.1 主要方法

ContentProvider 使用表格的形式管理数据,对外暴露四个操作方法,分别是:添加、删除、更新、查询(insert、delete、update、query):

添加数据(Binder 线程)
public abstract Uri insert(Uri uri, ContentValues values);

删除数据(Binder 线程)
public abstract int delete(Uri uri, String selection, String[] selectionArgs);

更新数据(Binder 线程)
public abstract int update(Uri uri, ContentValues values, String selection, String[] selectionArgs);

查询数据(Binder 线程)
public abstract Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder);

除了 4 个核心方法外,ContentProvider 还有其他比较重要的方法,例如:

启动回调(主线程)
public abstract boolean onCreate();

返回 Uri 对应的 MIME 类型(调用线程)
public abstract String getType(Uri uri);

需要注意:四个核心方法执行在 ContentProvider 注册进程,并在 Binder 线程池中执行,而不是主线程。考虑到存在多线程并发访问,为了保证数据安全在实现 ContentProvider 是还需要保证线程同步。

3.2 ContentProvider的使用

ContentProvider 的使用可以简单的归纳为以下几步:
1、创建自己的数据列表;
2、自定义ContentProvider实现相关的抽象方法;
3、在AndroidManifest中声明provider以及定义相关访问权限;
4 、通过ContentResolver根据URI进行增删改查。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值