Android学习笔记(十三):ContentProvider

概述

        ContentProvider作为安卓四大组件之一,它的作用是为不同的应用之间数据共享,提供统一的接口。我们知道安卓系统中应用内部的数据是对外隔离的,要想让其它应用能使用自己的数据(例如通讯录),这个时候就用到了ContentProvider
        ContentProvider实际上是对SQLiteOpenHelper的进一步封装,以一个或多个表的形式将数据呈现给外部应用,通过Uri映射来选择需要操作数据库中的哪个表,并对表中的数据进行增删改查处理。

URI

        URI(Uniform Resource Identifier)即统一资源标识符,是一个用于标识某一互联网资源名称的字符串。下面举个栗子:

在这里插入图片描述
        上面是一个完整的URI,其中HostPort一起为Authority,用于唯一标识一个ContentProvider,每个部分在安卓中都是可以通过代码获取的,下面这些方法可以获取:

  1. getScheme():获取URI中的Scheme字符串部分。
  2. getHost():获取URI中的Host部分。
  3. getPort():获取URI中的Port部分。
  4. getPath():获取URI中的Path部分。
  5. getQuery():获取URI中的Query部分。

MIME类型

        MIME(Multipurpose Internet Mail Extensions)即多用途互联网邮件扩展类型,是指定某种扩展名的文件用什么应用程序打开的方式类型。当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

类型/子类型(Content-Type/SubType) 扩展名
application/vnd.android.package-archive .apk
text/plain .txt
image/jpeg .jpeg
text/html .html
audio/x-pn-realaudio .rmvb
audio/mpeg .mp3
video/mp4 .mp4
image/png .png
application/json .json
application/pdf .pdf

ContentProvider如何共享数据

        ContentProvider通过URI来标识其他应用要访问的数据,而ContentResolver通过URI来定位自己要访问的数据,然后通过ContentResolver的增、删、改、查方法实现对共享数据的操作。还可以注册ContentObserver来监听数据是否发生了变化来对应的刷新页面。

UriMatcher类

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

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

static {
    //初始化,匹配不成功返回NO_MATCH(-1)。
    sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    
    //添加我们需要匹配的Uri,并把Uri和Uri_Code相关联
    sUriMatcher.addURI(AUTHORITY,"student",STUDENT_URI_CODE);
}

//通过match方法能够根据传递的uri匹配到对应的Uri_Code
int uriType = sUriMatcher.match(uri);

ContentUris类

        ContentUris类代码很短,只包含了withAppendedId()parseId()appendId()三个静态方法。
        调用withAppendedId()方法会在原始的uri后面添加一个id(值需要自己指定),调用parseId()方法可以取出这个id

Uri uri = Uri.parse("content://com.android.irving.provider/student");
//向原uri后添加一个值为1的id,得到一个新的uri
Uri withAppendedIdUri = ContentUris.withAppendedId(uri,1);
//取出这个id
long parseId = ContentUris.parseId(withAppendedIdUri);

        appendId()方法用于通过Uri.Builder方式生成的Uri使用。

Uri.Builder ub = new Uri.Builder();
//将Uri.Builder创建出来的Uri添加属性
ub.authority("com.android.irving.provider").appendPath("student");
//在Uri后面添加id并得到一个新的Uri
Uri.Builder appendIdUri = ContentUris.appendId(ub,1);

ContentProvider详解

        ContentProvider是一个抽象类,如果我们需要开发自己的内容提供者我们就需要继承这个类并复写其方法,需要实现的主要方法下:

//在创建ContentProvider时调用 
public boolean onCreate()

//用于查询指定URI的数据返回一个Cursor
/*
 * 第二个参数:告诉Provider要返回的内容(列Column)
 * 第三个参数:设置条件,相当于SQL语句中的where。null表示不进行筛选。如果我们只想返回名  * 称为张三的数据,第三个参数应该设置为:“= '张' ”。
* 第四个参数:selectionArgs,这个参数是要配合第三个参数使用的,如果你在第三个参数里面
* 有?,那么你在selectionArgs写的数据就会替换掉 ?
* 第五个参数:sortOrder,按照什么进行排序,相当于SQL语句中的Order by。如果想要结果按照
* ID的降序排列:“DESC”,模式为“ASC”升序排序。
*/
public Cursor query(Uri uri, String[] projection,String selection,String[] selectionArgs, String sortOrder)

//用于向指定URI的ContentProvider中添加数据
public Uri insert()

//用于删除指定URI的数据
public int delete()

//用于更新指定URI的数据
public int update()

//用于返回指定的URI中的数据MIME类型
public String getType()

        注意:数据访问的方法insert()delete()update()可能被多个线程同时调用,此时必须是线程安全的。

ContentProvider简单使用

  1. 创建自己的数据列表;
  2. 自定义类继承ContentProvider并实现相关的抽象方法,进行增删改操作后调用getContext().getContentResolver().notifyChange(uri,null)方法通知ContentObserver数据发生了变动,以便进行相应的操作。
  3. AndroidManifest中声明provider以及定义相关访问权限;

    <!-- student provider 访问权限声明 -->
    <permission android:name="com.android.irving.provider.READ_PERMISSION"
        android:label="student provider read permission"
        android:protectionLevel="normal">
    </permission>
    <permission android:name="com.android.irving.provider.WRITE_PERMISSION"
        android:label="student provider write permission"
        android:protectionLevel="normal">
    </permission>
    <!-- 声明ContentProvider -->
    <application>
        .......
        <provider
            android:authorities="com.android.irving.provider"
            android:name=".StudentContentProvider"
            android:readPermission="com.android.irving.provider.READ_PERMISSION"
            android:writePermission="com.android.irving.provider.WRITE_PERMISSION"
            android:exported="true">
        </provider>
        ......
    </application>
  1. 通过ContentResolver根据URI进行增删改查操作。
            权限声明时protectionLevel设置的是最低风险权限(normal),关于其他等级权限和说明如下:
权限等级 说明
normal 低风险权限,只要申请了就可以使用,安装时不需要用户确认。
dangerous 高风险权限,安装时需要用户确认授权才可以使用。
signature 只有当申请权限应用与声明此权限应用的数字签名相同时才能将权限授给它。
signatureOrSystem 签名相同或者申请权限的应用为系统应用才能将权限授给它。

ContentObserver类

        Android中提供的用来监听ContentProvider变化的抽象类,可以通过ContentResolverregisterContentObserver()unregisterContentObserver()方法来注册和注销ContentObserver监听器。当被监听的ContentProvider发生变化时,就会回调对应的ContentObserveronChange()方法。

补充

1、UI线程设置Handler传入ContentObserver中,当Uri中的内容发生变化时,在ContentObserveronChange()方法中通过此Handler回传数据给UI线程,通知UI线程更新数据。
2、在RecyclerViewAdapter中提供接口,用于增删改数据时刷新页面。在进行操作的Activity中发送广播给展示RecyclerViewActivity(主展示页面)并携带修改的信息,在主页面接收广播并通过接口提醒RecyclerView刷新数据。

发布了167 篇原创文章 · 获赞 230 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_39240270/article/details/100140664