zoukankan      html  css  js  c++  java
  • Android基础内容提供者ContentProvider的使用详解(转)

    1.什么是ContentProvider

    首先,ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用的比较少。 ContentProvider为不同的软件之间数据共享,提供统一的接口。也就是说,如果我们想让其他的应用使用我们自己程序内的数据,就可以使用 ContentProvider定义一个对外开放的接口,从而使得其他的应用可以使用咱们应用的文件、数据库内存储的信息。当然,自己开发的应用需要给其 他应用共享信息的需求可能比较少见,但是在Android系 统中,很多系统自带应用,比如联系人信息,图片库,音频库等应用,为了对其他应用暴露数据,所以就使用了ContentProvider机制。所以,我们 还是要学习ContentProvider的基本使用,在遇到获取联系人信息,图片库,音频库等需求的时候,才能更好的实现功能 。

    2.如何定义一个ContentProvider

    Android系统为了让我们更好的对外暴露数据,提供了统一的接口,所以定义了抽象类ContentProvider,因此,如果我们想对外提供数据,我们需要继承ContentProvider,并且实现下面的这几个方法:
    onCreate() 当我们的provider初始化时被调用,我们应该在这个方法里面完成部分初始化操作 query() 查询方法,用于给调用者返回数据 insert() 插入操作,用于让外部应用插入数据到内容提供者中 update() 更新操作,用于更新内容提供者的数据 delete() 用于删除数据 getType 返回内容提供者的MIME Type
    上面这些方法,当我们继承自ContentProvider的时候,eclipse会自动的给我们添加,但是这并不代表我们每个方法都需要自定义实现。如 果我们只希望给其他应用提供数据,而不允许其他应用修改我们的数据,那么我们只需要实现onCreate(),getType()和query()这三个 方法就可以了,其他的三个方法我们可以根据业务需求,实现或者是不实现。
    因为一般使用ContentProvider向外部暴露数据库的信息,因此,本篇将以使用ContentProvider向其他应用暴露数据库信息为例,讲解ContentProvider的基本使用。
    Android中SQLite数据库的创建和使用,本篇不再介绍,不清楚的请看这篇文章 SQLite数据库的简单实用。

    /**
     * 内容提供者
     * 
     * @author ZhaoKaiQiang
     * @time 2014年6月6日
     */
    public class StudentProvider extends ContentProvider {
        // 数据库操作类,用于获取SQLiteDatabase
        private MyDbOpenHelper dbHelper;
    
        private static final int STUDENT = 1;
        private static final int STUDENTS = 2;
    
        // UriMatcher类是一个很重要的类,因为我们需要根据传入的uri,来判断执行相对应的操作
        private static final UriMatcher MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    
        // 静态代码块用于初始化MATCHER需要匹配的uri
        static {
            // MATCHER.addURI(主机名(用于唯一标示一个ContentProvider,这个需要和清单文件中的authorities属性相同),路径(可以用来表示我们要操作的数据,路径的构建应根据业务而定),返回值(用于匹配uri的时候,作为匹配的返回值));
            MATCHER.addURI("com.example.mydbdemo.StudentProvider", "student", STUDENTS);
            MATCHER.addURI("com.example.mydbdemo.StudentProvider", "student/#", STUDENT);
        }
    
        // 进行数据的初始化操作
        @Override
        public boolean onCreate() {
            dbHelper = new MyDbOpenHelper(getContext());
            return false;
        }
    
        // 查询
        // 如果uri为        content://com.example.mydbdemo.StudentProvider/student
        // 则代表查询所有的student表内的数据
        // 如果uri为        content://com.example.mydbdemo.StudentProvider/student/6
        // 则代表查询student表内id=6的数据
        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    
            SQLiteDatabase db = dbHelper.getReadableDatabase();
            //判断传入的uri到底匹配哪一个,从而实现不同的业务需求
            switch (MATCHER.match(uri)) {
            //查询全部的学生信息
            case STUDENTS:
                //db.query(表明, 要查询的列(是一个String数组), where条件, where条件中的参数, groupBy, having, sortOrder);
                return db.query("student", projection, selection, selectionArgs, null, null, sortOrder);
            //查询某一个id对应的学生的信息
            case STUDENT:
                //取出我们要查询的数据的id
                long id = ContentUris.parseId(uri);
                String where = "id=" + id;
                //将selection查询信息拼接到我们的where条件中
                if (selection != null && !"".equals(selection)) {
                    where = selection + " and " + where;
                }
                return db.query("student", projection, where, selectionArgs, null, null, sortOrder);
            //如uri不匹配,抛出不合法参数的异常
            default:
                throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
            }
    
        }
    
        // 插入
        @Override
        public Uri insert(Uri uri, ContentValues values) {
            SQLiteDatabase db = dbHelper.getWritableDatabase();
            switch (MATCHER.match(uri)) {
            case STUDENTS:
                long id = db.insert("student", "name", values);
                return ContentUris.withAppendedId(uri, id);
            default:
                throw new IllegalArgumentException("Uri不匹配");
            }
    
        }
    
        //删除数据
        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            SQLiteDatabase db = dbHelper.getWritableDatabase();
            int count = 0;
            switch (MATCHER.match(uri)) {
            case STUDENTS:
                count = db.delete("student", selection, selectionArgs);
                return count;
    
            case STUDENT:
                long id = ContentUris.parseId(uri);
                String where = "id=" + id;
                if (selection != null && !"".equals(selection)) {
                    where = selection + " and " + where;
                }
                count = db.delete("student", where, selectionArgs);
                return count;
    
            default:
                throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
            }
        }
    
        //更新数据
        @Override
        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
            SQLiteDatabase db = dbHelper.getWritableDatabase();
            int count = 0;
            switch (MATCHER.match(uri)) {
            case STUDENTS:
                count = db.update("student", values, selection, selectionArgs);
                return count;
    
            case STUDENT:
                long id = ContentUris.parseId(uri);
                String where = "id=" + id;
                if (selection != null && !"".equals(selection)) {
                    where = selection + " and " + where;
                }
                count = db.update("student", values, where, selectionArgs);
                return count;
    
            default:
                throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
            }
        }
    
        // 用于获取MIME Type
        @Override
        public String getType(Uri uri) {
            switch (MATCHER.match(uri)) {
            case STUDENT:
                return "vnd.android.cursor.item/student";
            case STUDENTS:
                return "vnd.android.cursor.dir/student";
            default:
                throw new IllegalArgumentException("Unkwon Uri:" + uri.toString());
            }
    
        }
    
    }

    我们在定义好我们的ContentProvider之后,因为ContentProvider数据四大组件之一,因此我们还需要在AndroidManifest清单文件中进行注册才能使用,下面是注册信息

    <!-- 不要忘记exported这个属性,如果不加,可能会导致外部程序访问失败,错误信息为权限拒绝 -->
             <!-- authorities这个属性就是我们在ContentProvider中使用的addURI方法时的第一个参数的取值 -->
            <provider
                android:name="com.example.mydbdemo.StudentProvider"
                android:exported="true"
                android:authorities="com.example.mydbdemo.StudentProvider" >
            </provider>

    注意,provider的声明和activity一样,都是在application节点进行声明的。
    至此,我们就完成了我们自己的ContentProvider的生命,其他的应用现在就可以使用我们往外部暴露的数据信息了。

    3.外部应用如何使用我们的ContentProvider

    我们已经定义好了我们自己的ContentProvider,那么外部应用如何调用呢? 下面,我将新建一个测试单元工程,完成对ContentProvider的各个方法的测试
    添加方法测试

    //使用ContentProvider添加数据的测试
        public void testadd() throws Throwable {
            //获取ContentResolver对象,完成对ContentProvider的调用
            ContentResolver contentResolver = this.getContext().getContentResolver();
            //构建我们的uir,这个uri
            Uri insertUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student");
            ContentValues values = new ContentValues();
            values.put("name", "zhaokaikai");
            values.put("age", 91);
            values.put("school", "bbbb");
            //返回值为我们刚插入进入的数据的uri地址
            Uri uri = contentResolver.insert(insertUri, values);
            Log.i(TAG, uri.toString());
        }

    删除方法测试

    //使用ContentProvider删除数据的测试
        public void testDelete() throws Throwable {
            ContentResolver contentResolver = this.getContext().getContentResolver();
            //删除id为6的学生信息
            Uri deleteUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/6");
            contentResolver.delete(deleteUri, null, null);
        }

    修改方法测试

    //使用ContentProvider更新数据的测试
        public void testUpdate() throws Throwable {
            ContentResolver contentResolver = this.getContext().getContentResolver();
            //更新id = 6 的学生信息
            Uri updateUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/6");
            ContentValues values = new ContentValues();
            values.put("name", "testUp");
            values.put("age", "101");
            values.put("school", "ccccc");
            contentResolver.update(updateUri, values, null, null);
        }
    //使用ContentProvider查询数据的测试
        public void testFind() throws Throwable {
            ContentResolver contentResolver = this.getContext().getContentResolver();
            //这个uri用于查询所有的数据,若查询某个id的数据,则构建下面的uri
            //Uri selectUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student/要查询的id");
            Uri selectUri = Uri.parse("content://com.example.mydbdemo.StudentProvider/student");
            Cursor cursor = contentResolver.query(selectUri, null, null, null, "id desc");
            while (cursor.moveToNext()) {
                int id = cursor.getInt(cursor.getColumnIndex("id"));
                String name = cursor.getString(cursor.getColumnIndex("name"));
                int age = cursor.getInt(cursor.getColumnIndex("age"));
                String school = cursor.getString(cursor.getColumnIndex("school"));
                Log.i(TAG, "id=" + id + ",name=" + name + ",age=" + age +",school="+school);
            }
        }

    上面的方法都经过了单元测试。

    其他人的总结:{

    二、Uri类简介

    Uri代表了要操作的数据,Uri主要包含了两部分信息
    ①需要操作的ContentProvider
    ②对ContentProvider中的什么数据进行操作

    组成部分
    ①scheme:ContentProvider的scheme已经由Android所规定为content://
    ②主机名(Authority):用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。建议为公司域名,保持唯一性
    ③路径(path):可以用来表示我们要操作的数据,路径的构建应根据业务而定:

    要操作person表中id为10的记录
    content://cn.xyCompany.providers.personProvider/person/10

    要操作person表中id为10的记录的name字段
    content://cn.xyCompany.providers.personProvider/person/10/name

    要操作person表中的所有记录
    content://cn.xyCompany.providers.personProvider/person

    要操作的数据不一定来自数据库,也可以是文件等他存储方式,如要操作xml文件中user节点下的name节点

    content://cn.xyCompany.providers.personProvider/person/10/name

    把一个字符串转换成Uri,可以使用Uri类中的parse()方法
    Uri uri = Uri.parse(“content://cn.xyCompany.providers.personProvider/person”)

    三、UriMatcher、ContentUris和ContentResolver简介

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

    UriMatcher

    用于匹配Uri

    ①把需要匹配Uri路径全部给注册上

    // 常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)。
    UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

    // 若match()方法匹配content://cn.xyCompany.providers.personProvider/person路径则返回匹配码为1
    uriMatcher.addURI(“content://cn.xyCompany.providers.personProvider”,”person”, 1);

    // 若match()方法匹配content://cn.xyCompany.providers.personProvider/person/10路径则返回匹配码为2
    uriMatcher.addURI(“content://cn.xyCompany.providers.personProvider”,”person/#”, 1);

    ②注册完需要匹配的Uri后,就可以使用uriMatcher.match(uri)方法对输入的Uri进行匹配

    ContentUris
    ContentUris是对URI的操作类,其中的withAppendedId(uri, id)用于为路径加上ID部分,parseId(uri)方法用于从路径中获取ID部分方法很实用。
    Uri insertUri = Uri.parse(“content://cn.xyCompany.providers.personProvider/person” + id);等价于
    Uri insertUri = ContentUris.withAppendedId(uri, id);

    ContentResolver
    当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成。要获取ContentResolver 对象,可以使用Activity提供的getContentResolver()方法。 ContentResolver使用insert、delete、update、query方法来操作数据。
    }

  • 相关阅读:
    hiveserver2 with kerberos authentication
    python Basic usage
    python Quicksort demo
    Python HeapSort
    mrunit for wordcount demo
    CCDH证书
    Hadoop question list
    Hadoop Yarn core concepts
    Hadoop Resource
    Hadoop could not find or load main class
  • 原文地址:https://www.cnblogs.com/dayiran1222/p/5586544.html
Copyright © 2011-2022 走看看