三、基本组件(四)深入理解ContentProvider

1. ContentProvider介绍

ContentProvider一般为存储和获取数据提供统一的接口,可以在不同的应用程序之间共享数据。
ContentProvider的好处和用途:
(1)ContentProvider提供了对底层数据存储方式的抽象。比如下图中,底层使用了SQLite数据库,在用了ContentProvider封装后,及时你把数据库换成MongoDB,也不会对上层数据使用层代码产生影响。
这里写图片描述
(2)Android框架中的一些类需要使用ContentProvider类型的数据。如果想让数据可以使用在SyncAdapter,Loader,CursorAdapter等类上,就需要为数据做一层ContentProvider封装。
(3)ContentProvider为应用间的数据交互提供了一个安全的环境。它允许你把自己的应用数据根据需求开放给其他应用进行增删改查,而不用担心直接开放数据库权限带来的安全问题。

2.ContentResolver介绍

ContentResolver是对ContentProvider的封装,用于对不同的ContentProvider进行操作。一般情况下一台手机中会有很多个Provider应用,如果要了解使用每个ContentProvider的实现会很麻烦,所以Android为我们提供了ContentResolver来同意管理于不同ContentProvider间的操作。
这里写图片描述
我们可以在所有继承Context的类中通过调用getContentResolver( )来获得ContentResolver。但是ContentResolver是如何来区别不同的ContentProvider的呢,这就需要涉及到URI(Uniform Resource Identifier)。

3.ContentProvider中的URI介绍

ContentProvider中的URI有固定格式,如下图:
这里写图片描述
Scheme:ContentProvider的scheme已经由Android规定好,即“content://”
Authority:主机名,也就是授权信息,用以区别不同的ContentProvider,外部调用者可以根据这个标识来找到它;
Path:表名,用以区分ContentProvider中不同的数据表;
Id:Id号,用以区别表中的不同数据

4.ContentProvider开发步骤说明

(1)创建一个类,并继承ContentProvider;
(2)在AndroidManifest中配置声明
(3)定义UriMatcher

private UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);  //创建一个URI匹配器,参数为不匹配时的返回值
在onCreate中使用matcher.addURI("authorities","path",code);  //加入匹配的URI,如果匹配,则matcher.match(uri)返回code;

如果要匹配:content://authorities/path/数字  ,则matcher.addURI("authorites","path/#",code);

(4)重写增删改查等方法
onCreate():用于为操作数据做准备;
insert:插入数据,返回插入的记录所代表的URI;
update:更新数据,返回操作影响的记录行数;
delete:删除数据,返回操作影响的记录行数;
query:查询数据,返回Cursor;
getType:记录的类型,如果操作集合,则必须以vnd.android.cursor.dir开头,如果操作非集合,则必须以vnd.android.cursor.item开头,比如vnd.android.cursor.dir/person
(5)外部调用
ContentResolver resolver = this.getContext().getContentResolver();
resolver.insert();
resolver.update();
resolver.delete();
resolver.query();

5.应用举例

步骤一:创建PersonProvider.java

  public class PersonProvider extends ContentProvider {
        private DatabaseHelper mHelper;
        private SQLiteDatabase mDatabase;
        private UriMatcher mMatcher = new UriMatcher(UriMatcher.NO_MATCH);

        @Override
        public boolean onCreate() {
            mHelper = new DatabaseHelper(this.getContext());
//匹配:content://org.wxt.provides.personprovider/person,返回值为1
            mMatcher.addURI("org.wxt.provides.personprovider","person",1);
//匹配:content://org.wxt.provides.personprovider/person/数字,返回值为2
            mMatcher.addURI("org.wxt.provides.personprovider","person/#",2);
            return true;
        }

        @Nullable
        @Override
        public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String
                selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
            mDatabase = mHelper.getWritableDatabase();
            switch (mMatcher.match(uri)){
                case 1://查询所有记录
                    return mDatabase.query("person",projection,selection,selectionArgs,null,null,null);
                case 2://查询特定记录
                    long id = ContentUris.parseId(uri);
                    String where = "id="+id;
                    if(selection!=null&&!"".equals(selection)){//因为selection可能还包含其他的where语句,需要再加上 "and id=?"
                        where = where+" and"+selection;
                    }
                    return mDatabase.query("person",projection,where,selectionArgs,null,null,null);
                default:
                    throw new IllegalArgumentException("wrong uri");
            }
        }

        /*
        * 如果操作集合,则必须以vnd.android.cursor.dir开头
        * 如果操作非集合,则必须以vnd.android.cursor.item开头
        */
        @Override
        public String getType(Uri uri) {
            switch(mMatcher.match(uri)){
                case 1:
                    return "vnd.android.cursor.dir/person";
                case 2:
                    return "vnd.android.cursor.item/person";
                default:
                    return null;
            }
        }

        /**
         *
         * @param uri
         * @param values 插入的数据
         * @return
         */
        @Nullable
        @Override
        public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
            mDatabase = mHelper.getWritableDatabase();
            switch (mMatcher.match(uri)){
                case 1:
                    long rowid = mDatabase.insert("person",null,values);
                    return ContentUris.withAppendedId(uri,rowid);
                default:
                    throw new IllegalArgumentException("wrong uri");
            }
            return null;
        }

        @Override
        public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[]
                selectionArgs) {
            mDatabase = mHelper.getWritableDatabase();
            switch (mMatcher.match(uri)){
                case 1://删除全部记录
                    return mDatabase.delete("person",selection,selectionArgs);
                case 2: //删除特定id的记录
                    long id = ContentUris.parseId(uri);
                    String where = " id"+id;
                    if(selection!=null&&!"".equals(selection)){
                        where +=" and"+selection;
                    }
                    return mDatabase.delete("person",where,selectionArgs);
                default:
                    throw new IllegalArgumentException("wrong uri");
            }
        }

        @Override
        public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
            mDatabase = mHelper.getWritableDatabase();
            switch (mMatcher.match(uri)){
                case 1://更新全部记录
                    return mDatabase.update("person",values,selection,selectionArgs);
                case 2: //更新特定id的记录
                    long id = ContentUris.parseId(uri);
                    String where = " id"+id;
                    if(selection!=null&&!"".equals(selection)){
                        where +=" and"+selection;
                    }
                    return mDatabase.update("person",values,where,selectionArgs);
                default:
                    throw new IllegalArgumentException("wrong uri");
            }
        }
    }

步骤二:在AndroidManifest.xml注册

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android";
    package="com.example.administrator.myapplication">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

        <provider
            android:authorities="org.wxt.provides.personprovider"
            android:name=".PersonProvider"/>


    </application>

</manifest>

步骤三:测试类调用 ContentProviderTest.java

public class ContentProviderTest extends AndroidTestCase {
        public void testInsert()throws Exception{
            Uri uri = Uri.parse("content://org.wxt.provides.personprovider/person");
            ContentResolver resolver = this.getContext().getContentResolver();
            ContentValues contentValues = new ContentValues();
            contentValues.put("name","wxt");
            contentValues.put("age",16);
            resolver.insert(uri,contentValues);
        }

        public void testUpdate()throws Exception{
            Uri uri = Uri.parse("content://org.wxt.provides.personprovider/person/5");
            ContentResolver resolver = this.getContext().getContentResolver();
            ContentValues contentValues = new ContentValues();
            contentValues.put("name","wxt");
            contentValues.put("age",16);
            resolver.update(uri,contentValues,null,null);
        }


        public void testDelete()throws Exception{
            Uri uri = Uri.parse("content://org.wxt.provides.personprovider/person/5");
            ContentResolver resolver = this.getContext().getContentResolver();
            resolver.delete(uri,null,null);
        }


        public void testQuery()throws Exception{
            Uri uri = Uri.parse("content://org.wxt.provides.personprovider/person");
            ContentResolver resolver = this.getContext().getContentResolver();
            Cursor cursor = resolver.query(uri,null,null,null);
            while (cursor.moveToNext()){
                int id = cursor.getInt(cursor.getColumnIndex("id"));
                String name =cursor.getString(cursor.getColumnIndex("name"));
                int age = cursor.getInt(cursor.getColumnIndex("age"));
                Person person = new Person(id ,name,age);
            }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值