• android四大组件之ContentProvider(一)


    ContentProvider学习笔记

    1、 ContentProvider基本概念

    ContentProvider向我们提供了我们在应用程序之间共享数据的一种机制,虽然采用文件和SharedPreferences都可以实现应用程序间的数据共享,但是这样数据访问方式会因数据存储方式不同而不一样,如采用文件方式对外共享数据,需要对文件进行读写操作,采用SharedPreferences共享数据,需要使用SharedPreferences的API进行数据的读写,而使用ContentProvider则达到了不同应用程序间数据访问方式的统一。

    (1)     ContentProvider提供为存储和获取数据提供统一的接口。

    (2)     使用ContentProvider可以在不同的应用程序直接共享数据。

    (3)     Android为常见的一些数据提供了ContentProvider(包括音频、视频、图片和通讯录等)。

        ContentProvider使用表的形式来组织数据

    2、 URI[统一资源标识符]

    (1)     每一个ContentProvider都拥有一个公共的URI,这个URI用于标识这个

    ContentProvider所提供的数据。

    (2)     Android所提供的ContentProvider都存放在android.provider包当中。

    (3)     命名规范:Uri主要包含了两部分信息:1》需要操作的ContentProvider ,2》对ContentProvider中的什么数据进行操作,一个Uri由以下几部分组成:

     

      ContentProvider(内容提供者)的scheme已经由Android所规定, scheme为:content://
      主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
      路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
      要操作person表中id为10的记录,可以构建这样的路径:/person/10
      要操作person表中id为10的记录的name字段, person/10/name
      要操作person表中的所有记录,可以构建这样的路径:/person
      要操作xxx表中的记录,可以构建这样的路径:/xxx
      当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:
      要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
      如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:
      Uri uri = Uri.parse("content://com.ljq.provider.personprovider/person")

    3、 ContentProvider的实现方法

    (1)     query():查询

    (2)     insert():插入

    (3)     update():更新

    (4)     delete():删除

    (5)     getType():得到数据类型

    (6)     onCreate():创建时的回调函数

    4、 实现一个ContentProvider的步骤:

    (1)     定义一个类,继承ContentProvider

    (2)     定义一个CONTENT_URI常量,并添加供外界访问的接口

    (3)     编写代码实现ContentProvider的insert(),delete(),update(),query()等方法

    (4)     在AndroidManifest.xml文件中配置此ContentProvider

    5、 实例,编写StudentProvider

    (1)编写自己的StudentProvider类继承ContentProvider

    package com.demo.sqlite.provider;
    
    import com.demo.sqlite.dao.DBOpenHelper;
    
    import android.content.ContentProvider;
    import android.content.ContentUris;
    import android.content.ContentValues;
    import android.content.UriMatcher;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.net.Uri;
    import android.text.TextUtils;
    
    /**
     * 自定义一个学生的内容提供者
     * 
     * @author yinbenyang
     *
     */
    public class StudentProvider extends ContentProvider {
    
        private DBOpenHelper helper;
        private static final int NUM1 = 1;
        private static final int NUM2 = 2;
        SQLiteDatabase db = null;
        private static final String AUTHORITY = "come.demo.sqlite.studentprovider";
        // 常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
        private static final UriMatcher matcher = new UriMatcher(
                UriMatcher.NO_MATCH);
        // 添加两个供外界使用的接口
        static {
            // 如果match()方法匹配content://come.demo.sqlite.studentprovider/t_student路径,返回匹配码为1
            matcher.addURI(AUTHORITY, "t_student", NUM1);
            // 如果match()方法匹配content://come.demo.sqlite.studentprovider/t_student/1路径,返回匹配码为2
            matcher.addURI(AUTHORITY, "t_student/#", NUM2); // #代表通配符
        }
    
        @Override
        public boolean onCreate() {
            helper = new DBOpenHelper(this.getContext());
            db = helper.getWritableDatabase();
            return true;
        }
    
        // 查询操作
        @Override
        public Cursor query(Uri uri, String[] projection, String selection,
                String[] selectionArgs, String sortOrder) {
            Cursor cursor = null; // 用于储存一个查询的 结果
            switch (matcher.match(uri)) {
            // content://come.demo.sqlite.studentprovider/t_student
            case NUM1:
                cursor = db.query("t_student", projection, selection,
                        selectionArgs, null, null, sortOrder);
                break;
            // content://come.demo.sqlite.studentprovider/t_student/#
            case NUM2:
                long sid = ContentUris.parseId(uri); // 从uri中获取id的值
                String where = TextUtils.isEmpty(selection) ? "sid = ?" : selection
                        + "sid = ?";
                String params[] = new String[] { String.valueOf(sid) };
                if (!TextUtils.isEmpty(selection) && selectionArgs != null) {
                    params = new String[selectionArgs.length + 1];
                    for (int i = 0; i < selectionArgs.length; i++) {
                        params[i] = selectionArgs[i];
                    }
                    params[selectionArgs.length + 1] = String.valueOf(sid);
                }
                cursor = db.query("t_student", projection, where, params, null,
                        null, sortOrder);
                break;
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
            }
            return cursor;
        }
    
        // 返回当前Url所代表数据的MIME类型
        @Override
        public String getType(Uri uri) {
            switch (matcher.match(uri)) {
            case NUM1:
                // 如果操作的数据属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头
                return "vnd.android.cursor.dir/student";
            case NUM2:
                // 如果要操作的数据属于非集合类型数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头
                return "vnd.android.cursor.item/student";
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
            }
        }
    
        // 插入操作
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            long sid = 0; // 用于存储插入成功后的记录的id
            switch (matcher.match(uri)) {
            // content://come.demo.sqlite.studentprovider/t_student
            case NUM1:
                sid = db.insert("t_student", "sname", values);
                // withAppendedId方法用于在uri后面追加一个sid的值
                return ContentUris.withAppendedId(uri, sid);
                // content://come.demo.sqlite.studentprovider/t_student/#
            case NUM2:
                sid = db.insert("t_student", "sname", values);
                String path = uri.toString();
                // 后面的id值更新
                return Uri
                        .parse(path.substring(0, path.lastIndexOf("/") + 1) + sid);
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
            }
        }
    
        // 删除操作
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            int count = 0; // 记录删除的结果
            switch (matcher.match(uri)) {
            // content://come.demo.sqlite.studentprovider/t_student
            case NUM1:
                count = db.delete("t_student", selection, selectionArgs);
                break;
            // content://come.demo.sqlite.studentprovider/t_student/#
            case NUM2:
                long sid = ContentUris.parseId(uri); // 从uri中获取id的值
                String where = TextUtils.isEmpty(selection) ? "sid = ?" : selection
                        + "sid = ?";
                String params[] = new String[] { String.valueOf(sid) };
                if (!TextUtils.isEmpty(selection) && selectionArgs != null) {
                    params = new String[selectionArgs.length + 1];
                    for (int i = 0; i < selectionArgs.length; i++) {
                        params[i] = selectionArgs[i];
                    }
                    params[selectionArgs.length + 1] = String.valueOf(sid);
                }
                count = db.delete("t_student", where, params);
                break;
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
            }
            return count;
        }
    
        // 更新操作
        @Override
        public int update(Uri uri, ContentValues values, String selection,
                String[] selectionArgs) {
            int count = 0; // 记录修改的结果
            switch (matcher.match(uri)) {
            // content://come.demo.sqlite.studentprovider/t_student
            case NUM1:
                count = db.update("t_student", values, selection, selectionArgs);
                break;
            // content://come.demo.sqlite.studentprovider/t_student/#
            case NUM2:
                long sid = ContentUris.parseId(uri); // 从uri中获取id的值
                String where = TextUtils.isEmpty(selection) ? "sid = ?" : selection
                        + "sid = ?";
                String params[] = new String[] { String.valueOf(sid) };
                if (!TextUtils.isEmpty(selection) && selectionArgs != null) {
                    params = new String[selectionArgs.length + 1];
                    for (int i = 0; i < selectionArgs.length; i++) {
                        params[i] = selectionArgs[i];
                    }
                    params[selectionArgs.length + 1] = String.valueOf(sid);
                }
                count = db.update("t_student", values, where, params);
                break;
            default:
                throw new IllegalArgumentException("Unknown URL " + uri);
            }
            return count;
        }
    
    }

    说明,上述程序是在之前写的sqlite基础上扩展的,不清楚的童鞋可以查看我的sqlite学习笔记ANDROID数据存储之SQLITE(二),DBOpenHelper为sqlite帮助类

    (2)在AndroidManifest.xml文件中声明自己的Provider

     <provider android:name="com.demo.sqlite.provider.StudentProvider"
                android:authorities="come.demo.sqlite.studentprovider"></provider>

    至此,自定义内容提供者编写完成,提供了content://come.demo.sqlite.studentprovider/t_student和content://come.demo.sqlite.studentprovider/t_student/#两种方式来供外界使用,下一章将讲解其他应用程序如何来访问这个自定义的内容提供者

    ------------------------------------------------------------------------------------------分割线--------------------------------------------------------------------------------------------------------------------------------

    课外扩充知识:

    UriMatcher类和ContentUris类的介绍

    因为Uri代表了要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据。Android系统提供了两个用于操作Uri的工具类,分别为UriMatcher和ContentUris 

    (1)UriMatcher类用于匹配Uri

    //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
    UriMatcher  sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    //如果match()方法匹配content://come.demo.sqlite.studentprovider/person路径,返回匹配码为1
    sMatcher.addURI("come.demo.sqlite.studentprovider", "person", 1);//添加需要匹配uri,如果匹配就会返回匹配码
    //如果match()方法匹配content://come.demo.sqlite.studentprovider/person/230路径,返回匹配码为2
    sMatcher.addURI("come.demo.sqlite.studentprovider", "person/#", 2);//#号为通配符
    switch (sMatcher.match(Uri.parse("content://come.demo.sqlite.studentprovider/person/10"))) { 
       case 1
         break;
       case 2
         break;
       default://不匹配
         break;
    }

    注册完需要匹配的Uri后,就可以使用sMatcher.match(uri)方法对输入的Uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://come.demo.sqlite.studentprovider/person路径,返回的匹配码为1 

    (2)ContentUris类用于操作Uri路径后面的ID部分

      withAppendedId(uri, id)用于为路径加上ID部分

    Uri uri = Uri.parse("content://come.demo.sqlite.studentprovider/person")
    Uri resultUri = ContentUris.withAppendedId(uri, 10); 
    //生成后的Uri为:content://come.demo.sqlite.studentprovider/person/10

      parseId(uri)方法用于从路径中获取ID部分:

    Uri uri = Uri.parse("content://come.demo.sqlite.studentprovider/person/10")
    long personid = ContentUris.parseId(uri);//获取的结果为:10
  • 相关阅读:
    博客背景美化——动态雪花飘落
    尼姆博弈+SG函数
    2016 CCPC-Final-Wash(优先队列+贪心)
    【php】---mysql语法增、删、改、查---【巷子】
    【php】---mysql---基本操作及使用---【巷子】
    【Object.prototype.toString.call()】---判断某个对象属于哪种内置类型------【巷子】
    【webpack】---模块打包机webpack基础使用---【巷子】
    设计模式---003代理模式---【巷子】
    设计模式---002适配模式---【巷子】
    设计模式---001单例模式---【巷子】
  • 原文地址:https://www.cnblogs.com/yby-blogs/p/4548086.html
Copyright © 2020-2023  润新知