zgq105 / blog

2 stars 0 forks source link

Android四大组件之ContentProvider #9

Open zgq105 opened 5 years ago

zgq105 commented 5 years ago

ContentProvider image

1. 什么是ContentProvider?作用是什么?

ContentProvider是安卓四大组件之一,它是一种Android应用之间数据共享的机制。它主要是通过一种协议规则进行应用之间的数据共享,比如,我们调用手机通讯录的时候使用的就是一种内容提供者的实现。

2. ContentProvider通信基础

ContentProvider通信的基础是基于Uri(统一资源标识符)的机制,外界应用程序就是通过Uri来获取到对应的内容提供者,从起对其进行增删改查的操作。内容提供者的URI格式如下: content://com.zgq.provider/User/1,其中content表示的是内容提供者的协议格式;com.zgq.provider表示的是授权信息authority,为了增强识别度,命名通常是包名+xxProvider;/User/1是路径部分,其中User表示某个实体,可以理解某个表,而1表示某个表的某条记录。

URI两个常用通配符和# 表示匹配任意长度的任何有效字符的字符串,比如content://com.zgq.provider/*,表示匹配这个内容提供者的所有信息。

表示匹配任意长度的数字字符的字符串,比如content://com.zgq.provider/User/#,表示匹配这个内容提供者User表中的所有记录。

MIME类型有2种形式:

  1. 单条记录:vnd.android.cursor.item/自定义
  2. 多条记录:vnd.android.cursor.dir/自定义

3. 构建ContentProvider

自定义内容提供者主要是通过实现ContentProvider抽象类,并重写实现内部增删改查的方法。 //示例代码

public class ContentProvider1 extends ContentProvider {

    private static final UriMatcher mMatcher;
    private static final String AUTHORITY = "com.zgq.android_demo.cp_demo.contentProvider1";
    private static final int TB1_CODE = 1;//表1标识码
    private static final int TB2_CODE = 2;//表2标识码

    private SQLiteDatabase mSQLiteDatabase;
    private DbHelper mDbHelper;

    static {
        //初始化UriMatcher对象
        mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        mMatcher.addURI(AUTHORITY, "tb1", TB1_CODE);
        mMatcher.addURI(AUTHORITY, "tb2", TB2_CODE);
        // 若URI资源路径 = content://com.zgq.android_demo.cp_demo.contentProvider1/tb1 ,则返回注册码TB1_CODE
        //若URI资源路径 = content://com.zgq.android_demo.cp_demo.contentProvider1/tb2 ,则返回注册码TB2_CODE

    }

    @Override
    public boolean onCreate() {
        mDbHelper = new DbHelper(getContext());
        mSQLiteDatabase = mDbHelper.getWritableDatabase();
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        return mSQLiteDatabase.query(getTableName(uri), projection, selection, selectionArgs, null, null, sortOrder);
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        mSQLiteDatabase.insert(getTableName(uri), null, values);
        return uri;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }

    private String getTableName(Uri uri) {
        String tbName = null;
        switch (mMatcher.match(uri)) {
            case TB1_CODE: {
                tbName = "tb1";
                break;
            }
            case TB2_CODE: {
                tbName = "tb2";
                break;
            }
            default:
                break;
        }

        return tbName;
    }
}

关键API: UriMatcher,Uri;其中UriMatcher主要建立Uri和表的映射关系,根据调用方传入的Uri,便可以通过UriMatcher找到对应的表,进而进行操作。

4. 使用ContentProvider

使用ContentProvider主要用到Uri和ContentResolver类,其中Uri标识要操作的是哪个内容提供者,而ContentResolver封装好了和ContentProvider 对应的API用于操作对应的数据。 //示例代码:

//插入
ContentValues values = new ContentValues();
values.put("id", 1);
values.put("name", "zgq");
this.getContentResolver().insert(uri, values);

//查询
this.getContentResolver().query(uri, null, "id=?", new String[]{"1"}, null);

5. 小结

关于内容提供者的几点小结: 1. 内容提供者是跨进程共享数据的一种机制,通过统一的API操作方式对外提供数据。 2. 数据提供方主要继承ContentProvider类,实现好对外共享的数据资源;而调用方主要通过ContentResolver和Uri来操作对应的数据资源。 3. 内容提供者是通过Uri协议格式交换对应数据的。 4. 内容提供者内部的通信机制是通过Binder机制实现的。