IPC机制--利用ContentProvider

时间:2022-10-17 16:15:40

本例Git地址:https://github.com/NoClay/MessagerTest.git

为什么使用ContentProvider?

ContentProvider是Android中提供的专门用于不同应用间进行数据共享的方式,从这点来看,它天生就是为了进程间通信的,和Messenger一样,ContentProvider的底层实现同样是Binder。

怎样使用ContentProvider?

自定义ContentProvider需要实现以下几个方法:

方法名 含义
onCreate 创建ContentProvider,初始化工作
getType 返回一个Uri请求所对应的MIME类型,比如照片,视频等,可以直接在方法中返回null或者*/*
query 查找
update 更新
insert 插入
delete 删除

对于ContentProvider数据存储的实现,我们可以选择使用文件,内存中的对象,也可以使用SQLite实现。

1. 实现SQLite

package com.example.no_clay.messagertest.Item255;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
* Created by no_clay on 2017/2/28.
*/


public class DBOpenHelper extends SQLiteOpenHelper {

public static final String DB_NAME = "book_provider.db";
public static final String BOOK_TABLE_NAME = "book";
public static final String USER_TABLE_NAME = "user";
public static final int DB_VERSION = 1;
public static final String CREATE_BOOK_TABLE = "create table if not exists " +
BOOK_TABLE_NAME + " (id text primary key, name text)";
public static final String CREATE_USER_TABLE = "create table if not exists " +
USER_TABLE_NAME + " (id text primary key, name text)";

public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK_TABLE);
db.execSQL(CREATE_USER_TABLE);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
}

2. 实现自定义的ContentProvider

package com.example.no_clay.messagertest.Item255;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.Nullable;
import android.util.Log;

import com.example.no_clay.messagertest.Util.MyConstants;

/**
* Created by no_clay on 2017/2/28.
*/


public class BookProvider extends ContentProvider {
private static final String TAG = "BookProvider";
public static final String AUTHORITY = MyConstants.PACKAGE_NAME + ".BookProvider";
public static final Uri BOOK_CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/book");
public static final Uri USER_CONTENT_URI = Uri.parse("content://" + AUTHORITY
+ "/user");
public static final int BOOK_URI_CODE = 0;
public static final int USER_URI_CODE = 1;
public static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
public Context mContext;
private SQLiteDatabase mDatabase;


static {
URI_MATCHER.addURI(AUTHORITY, "book", BOOK_URI_CODE);
URI_MATCHER.addURI(AUTHORITY, "user", USER_URI_CODE);
}

private String getTableName(Uri uri){
String tableName = null;
switch (URI_MATCHER.match(uri)){
case 0:tableName = DBOpenHelper.BOOK_TABLE_NAME;
break;
case 1:tableName = DBOpenHelper.USER_TABLE_NAME;
break;
default:break;
}
return tableName;
}

@Override
public boolean onCreate() {
Log.d(TAG, "onCreate: thread = " + Thread.currentThread().getName());
mContext = getContext();
mDatabase = new DBOpenHelper(mContext,
DBOpenHelper.DB_NAME,
null,
DBOpenHelper.DB_VERSION).getWritableDatabase();
// new Thread(new Runnable() {
// @Override
// public void run() {
// initData();
// }
// }).start();
return false;
}

// private void initData() {
// mDatabase.execSQL("insert into book values('num012', 'Android')");
// ContentValues value = new ContentValues();
// value.put("id", "num014");
// value.put("name", "Java编程思想");
// mDatabase.insert(DBOpenHelper.BOOK_TABLE_NAME, null, value);
// value.clear();
// value.put("id", "num016");
// value.put("name", "Android开发艺术探索");
// mDatabase.insert(DBOpenHelper.BOOK_TABLE_NAME, null, value);
// value.clear();
// value.put("id", "04141087");
// value.put("name", "高XX");
// mDatabase.insert(DBOpenHelper.USER_TABLE_NAME, null, value);
// value.clear();
// value.put("id", "04141085");
// value.put("name", "莫X");
// mDatabase.insert(DBOpenHelper.USER_TABLE_NAME, null, value);
// value.clear();
// value.put("id", "04141086");
// value.put("name", "张XX");
// mDatabase.insert(DBOpenHelper.USER_TABLE_NAME, null, value);
//
// }

@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
Log.d(TAG, "query: thread = " + Thread.currentThread().getName());
String table = getTableName(uri);
if (table == null){
throw new IllegalArgumentException("不支持的URI");
}
return mDatabase.query(table, projection, selection, selectionArgs,
null, null, sortOrder, null);
}

@Nullable
@Override
public String getType(Uri uri) {
Log.d(TAG, "getType: thread = " + Thread.currentThread().getName());
return null;
}

@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.d(TAG, "insert: thread = " + Thread.currentThread().getName());
Log.d(TAG, "insert: uri = " + uri);
String table = getTableName(uri);
if (table == null){
throw new IllegalArgumentException("不支持的URI");
}
mDatabase.insert(table, null, values);
mContext.getContentResolver().notifyChange(uri, null);
return null;
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.d(TAG, "delete: thread = " + Thread.currentThread().getName());
String table = getTableName(uri);
if (table == null){
throw new IllegalArgumentException("不支持的URI");
}
int count = mDatabase.delete(table, selection, selectionArgs);
if (count > 0){
getContext().getContentResolver().notifyChange(uri, null);
}
return count;
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
Log.d(TAG, "update: thread = " + Thread.currentThread().getName());
String table = getTableName(uri);
if (table == null){
throw new IllegalArgumentException("不支持的URI");
}
int row = mDatabase.update(table, values, selection, selectionArgs);
if (row > 0){
getContext().getContentResolver().notifyChange(uri, null);
}
return 0;
}
}

3. 注册ContentProvider组件

        <provider
android:name=".Item255.BookProvider"
android:authorities="com.example.no_clay.messagertest.BookProvider"
android:permission="com.example.no_clay.messagertest.PROVIDER"
android:process=":provider"/>

注意:
ContentProvider的onCreate方法由系统进行回调并运行在主线程方法中,而其他五个方法由外界回调并运行在Binder线程池中,这一点结果如下验证了:

03-01 15:45:41.168 12129-12129/com.example.no_clay.messagertest:provider D/BookProvider: onCreate: thread = main
03-01 15:45:41.176 12129-12146/com.example.no_clay.messagertest:provider D/BookProvider: query: thread = Binder_2
03-01 15:45:41.183 11082-11082/com.example.no_clay.messagertest D/BookProviderActivity: onCreate: book name = 程序设计的艺术
03-01 15:45:41.183 11082-11082/com.example.no_clay.messagertest D/BookProviderActivity: onCreate: book name = Android
03-01 15:45:41.183 11082-11082/com.example.no_clay.messagertest D/BookProviderActivity: onCreate: book name = Java编程思想
03-01 15:45:41.183 11082-11082/com.example.no_clay.messagertest D/BookProviderActivity: onCreate: book name = Android开发艺术探索
03-01 15:45:41.183 11082-11082/com.example.no_clay.messagertest D/BookProviderActivity: onCreate: book name = 程序设计的艺术
03-01 15:45:41.185 12129-12146/com.example.no_clay.messagertest:provider D/BookProvider: query: thread = Binder_2
03-01 15:45:41.187 11082-11082/com.example.no_clay.messagertest D/BookProviderActivity: query user:com.example.no_clay.messagertest.Data.User@42ca9ed8
03-01 15:45:41.187 11082-11082/com.example.no_clay.messagertest D/BookProviderActivity: query user:com.example.no_clay.messagertest.Data.User@42caa308
03-01 15:45:41.188 11082-11082/com.example.no_clay.messagertest D/BookProviderActivity: query user:com.example.no_clay.messagertest.Data.User@42caa658