Android四大控件之ContentProvider

Hi,众猿们,今天咱们讲讲ContentProvider(内容提供者)对象。在Android系统中,ContentProvider为我们提供了一种跨应用共享数据的机制,即通过该对象,我们可以本应用的数据对外暴露,以供其它应用访问。开始介绍本之前对象我们需要介绍如何表示一个资源的信息(如它在什么位置,该怎么用等),这一知识涉及到两个对象:Uri和URL
   Uri:Uniform Resource Identifier,即统一资源标识符,用来唯一的标识一个资源,有时并未明确地表示出了资源的位置,有时由三部分组成:
     1.访问资源的命名机制 :表明访问该资源需要使用什么协议,如http协议
     2.存放资源的主机名 (authority):表明该资源所在的大致位置,如其所在的主机ip地址,当该资源是数据库的某个表中的一条数据时,这一部分还可以是该数据库所在的应用的唯一标示
     3.资源自身的路径(path) :这部分对资源的位置进一步进行说明,如文件资源的文件名,数据库中的一条数据的主键值等
   URL:Uniform Resource Location,即统一资源定位符,它是一种具体的Uri,不仅唯一标识资源,而且还明确地表示出了资源的位置,也由上面的三部分组成。
数据也是一种资源,Android系统跨应用访问数据时是通过Uri来标示数据的,当我们希望访问其它程序的数据时,首先要确定该数据的Uri。
 如:一个安卓程序中有一个包:lmz.contentprovider.provider,其作用是提供数据供其他应用,其SQLite数据库中有一张表,名为table,我们想在其它程序中访问该表中主键值为1的一条数据,则我们可以确定该条数据的Uri的各部分值为:
   访问资源的命名机制:content(安卓中跨应用访问数据采用的是content协议)
   存放资源的主机名 :在这个例子中为该应用程序的唯一标示,一般我们就采用应用程序中起共享数据作用的包名 :lmz.contentprovider.provider
   资源的路径 :这里其值为:table/1
该Uri的完整值为:     
   content://lmz.contentprovider.provider/table/1。
这也是Uri的一般格式(是不是和网址的格式很像)。
但有时我们也会碰到如下  Uri:

 content://lmz.contentprovider.provider/table。
前面说过,Uri有时并未明确地表示出了资源的位置,因此这种Uri表示我们要访问table表中的每一条数据(你也可以认为该Uri明确地指明了我们要访问的是一张数据表)。 以上就是Uri常见的两种类型。我们调用Uri的静态方法:parse(),该方法需要传入一个字符串型的参数,即可将上述字符串转化成Uri对象。
现在我们已经确定了Uri,就要开始访问数据了, 这是我们需要使用ContentResolver(内容解决者)对象了,该对象用于访问其它程序的数据(一般都是数据库中的数据):
    1.ContentValues对象:用于辅助操作数据表的对象,代表数据表中的一条数据,该对象内部储存着一对对的键值对,其键为String类型,表示数据库的对应的列,而键对应的值就代表了这条数据在该列的值
    2.获取ContentResolver对象:调用Context对象的getContentResolver方法即可。
    3.操作Uri所标示的数据:调用ContentResolver对象的如下方法即可完成相关操作(附带这些方法的完整参数):
        1.insert方法:在指定的Uri(一般代表一张数据表)处插入一条数据,其返回值为插入数据的Uri,其参数为:
           Uri uri:被操作的数据表的Uri
           ContentValues values : 被插入的数据
        2.delete (Uri url, String where, String[] selectionArgs):删除数据,其返回结果为受影响的数据的条数
        3.update(Uri uri, ContentValues values, String where, String[] selectionArgs):更新数据其返回结果为受影响的数据的条数
        4.query(uri, projection, selection, selectionArgs, sortOrder):查询Uri所对应的数据,该方法会返回一个Cursor对象,我们遍历Cursor对象就可获得查询结果上面各方法的参数的含义分别为:

通过ContentResolver对象我们可以访问手机中的联系人、照片、音乐等数据。

下面我我们说说如何使用ContentProvider将本程序中的数据提供给其它程序访问。 ,首先我们需要判断访问数据的Uri的类型。在上面我们了解了Uri一共有两种类型:标示一张数据表的,标示一张数据表中的某一条数据的。在实际中如何表示这两种类型的Uri呢?这时就要用到通配符了。通配符一共有两种:
    1. * :表示匹配任意长度的字符串
    2. # :表示匹配任意长度的数字

因此,两种Uri可分别表示为:
   content://lmz.contentprovider.provider/table : 标示数据表
   content://lmz.contentprovider.provider/table/# : 标示数据表中的某一条数据(假设该表中数据的主键是数字)
   content://lmz.contentprovider.provider/table/* : 标示数据表中的某一条数据(假设该表中数据的主键是字符串)

  安卓系统为我们提供了一个类UriMatcher对象(其内部是一个树形结构),来匹配这两种Uri,其使用方法为:
   1.获取实例:直接调用其构造方法即可,该方法需要传入一个参数:我们一般转入UriMatcher类中的静态变量NO_MATCH即可,表示无匹配结果时的返回值
   2.添加Uri的种类:调用UriMatcher对象的addUri方法,其参数列表为:
       String authority :该Uri对应的主机名
       String path :该Uri对应的路径
       int code : 匹配成功时的返回码
    3.匹配Uri:调用match方法即可,该方法接收一个Uri对象,返回匹配结果

  接下来我们就要自定义一个ContentProvider对象了,需继承自系统的ContentProvider:
public class MyContentProvider extends ContentProvider{
    //Uri的主机名
    public static final String AUTHORYTY = "lmz.contentprovider.provider";
    //供外部访问的数据表
    public static final String TABLE = "table";

    public static final int TABLE_DIR = 0;//Uri访问的是一张数据表时的匹配结果
    public static final int TABLE_ITEM = 1;//Uri访问的是一条数据时的匹配结果

    private static UriMatcher matcher;//判断访问Uri类型的对象
    private SQLiteOpenHelper helper;//用于获取数据库实例并操作数据
    //对UriMatcher对象进行实例化
    static{
        matcher = new UriMatcher(UriMatcher.NO_MATCH);
        matcher.addURI(AUTHORYTY, TABLE, TABLE_DIR);//添加访问数据表的Uri
        matcher.addURI(AUTHORYTY, TABLE + "/#", TABLE_ITEM);//添加访问数据表的Uri
    }

    /**
     * 对象刚被创建时调用
     */
    @Override
    public boolean onCreate() {
        return false;
    }
    /**
     * 插入数据时调用
     */
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }
    /**
     * 删除数据时调用,首先要利用UriMatcher对象判断Uri的种类
     */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        //在其它方法中也要先做如此的判断
        switch(matcher.match(uri)){
        case TABLE_DIR:
            break;
        case TABLE_ITEM:
            //调用Uri的
            break;
        default:
            break;
        }
        return 0;
    }
    /**
     * 更新数据时调用,首先要利用UriMatcher对象判断Uri的种类
     */
    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {

        return 0;
    }
    /**
     * 查询数据时调用,首先要利用UriMatcher对象判断Uri的种类
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        return null;
    }

    /**
     * 返回Uri标示的数据的Mime类型(MIME是描述消息内容类型的因特网标准)
     *      1.必须以vnd开头
     *      2.如果该Uri标示的是多条数据,则后接:android.cursor.dir/
     *        如果该Uri标示的是多条数据,则后接:android.item.dir/
     *      3.最后接上 :vnd..
     * 该方法的具体作用本猿猿也不太清楚,有个解释是android系统可以利用该方法识别出Uri标示的是单条还是多条数据
     */
    @Override
    public String getType(Uri uri) {
        return null;
    }
}
关注微信公众号 :猿聚于此,可获得更多相关文章。

你可能感兴趣的:(android,个人,数据储存,android)