本章节讲述使用ContentProvider实现进程内通信 数据来源是SQLite
1.ContentProvider实现类
public class MyContentProvider extends ContentProvider {
private Context mContext;
private DBSQLiteOpenHelper mDbHelper = null;
private SQLiteDatabase db = null;
public static final String AUTOHORITY = "com.wjn.mycontentprovider";//设置ContentProvider的唯一标识 AndroidManifest.xml配置
public static final int User_Code = 1;
public static final int Job_Code = 2;
// UriMatcher类使用:在ContentProvider 中注册URI
private static final UriMatcher mMatcher;
static {
mMatcher = new UriMatcher(UriMatcher.NO_MATCH);
/**
* 初始化
* */
// 若URI资源路径 = content://com.wjn.mycontentprovide/user ,则返回注册码User_Code
mMatcher.addURI(AUTOHORITY, "user", User_Code);
// 若URI资源路径 = content://com.wjn.mycontentprovide/job ,则返回注册码Job_Code
mMatcher.addURI(AUTOHORITY, "job", Job_Code);
}
/**
* onCreate方法
*/
@Override
public boolean onCreate() {
mContext = getContext();
mDbHelper = new DBSQLiteOpenHelper(getContext(), "cdsp.db", null, 1);
db = mDbHelper.getReadableDatabase();
db.execSQL("delete from user");//删除user表中所有信息 可以做别的操作
db.execSQL("delete from job");//删除job表中所有信息 可以做别的操作
return true;
}
/**
* 增
*/
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
// 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
String table = getTableName(uri);
// 向该表添加数据
db.insert(table, null, values);
// 当该URI的ContentProvider数据发生变化时,通知外界(即访问该ContentProvider数据的访问者)
mContext.getContentResolver().notifyChange(uri, null);
return uri;
}
/**
* 删
*/
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
// 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
String table = getTableName(uri);
return db.delete(table, selection, selectionArgs);
}
/**
* 改
*/
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
// 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
String table = getTableName(uri);
return db.update(table, values, selection, selectionArgs);
}
/**
* 查
*/
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
// 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
String table = getTableName(uri);
// 查询数据
return db.query(table, projection, selection, selectionArgs, null, null, sortOrder, null);
}
/**
* getType方法 获取数据类型
*/
@Nullable
@Override
public String getType(@NonNull Uri uri) {
// 由于不展示,此处不作展开
return null;
}
/**
* 根据URI匹配 URI_CODE,从而匹配ContentProvider中相应的表名
*/
private String getTableName(Uri uri) {
String tableName = null;
switch (mMatcher.match(uri)) {
case User_Code:
tableName = "user";
break;
case Job_Code:
tableName = "job";
break;
}
return tableName;
}
}
2.AndroidManifest.xml配置文件
<provider
android:name=".test.MyContentProvider"
android:authorities="com.wjn.mycontentprovider"
android:enabled="true"
android:exported="true">
</provider>
说明
android:exported属性设置成true:可被其他应用使用;
android:exported属性设置成false:只能被自己所在的应用使用;
3.SQLiteOpenHelper实现类
/**
* SQLiteOpenHelper继承类
*/
public class DBSQLiteOpenHelper extends SQLiteOpenHelper {
/**
* 构造方法
*/
public DBSQLiteOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
/**
* onCreate 建表
*/
@Override
public void onCreate(SQLiteDatabase db) {
String user_sql = "CREATE TABLE user( id INTEGER, name VARCHAR(10), describe TEXT)";
String job_sql = "CREATE TABLE job( id INTEGER, name VARCHAR(10), describe TEXT)";
db.execSQL(user_sql);
db.execSQL(job_sql);
}
/**
* onUpgrade方法 版本更新
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String user_sql = "DROP TABLE IF EXISTS user";
String job_sql = "DROP TABLE IF EXISTS job";
db.execSQL(user_sql);
db.execSQL(job_sql);
onCreate(db);
}
}
4.java代码调用
public class ContentProviderActivity extends AppCompatActivity implements View.OnClickListener {
private TextView textView1;
private TextView textView2;
private TextView textView3;
private TextView textView4;
private TextView textView11;
private TextView textView22;
private TextView textView33;
private TextView textView44;
private TextView textView5;
private Uri uri_user;
private Uri job_user;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contentprovider);
initView();
}
/**
* 初始化各种View
*/
private void initView() {
textView1 = findViewById(R.id.activity_contentprovider_textview1);
textView2 = findViewById(R.id.activity_contentprovider_textview2);
textView3 = findViewById(R.id.activity_contentprovider_textview3);
textView4 = findViewById(R.id.activity_contentprovider_textview4);
textView11 = findViewById(R.id.activity_contentprovider_textview11);
textView22 = findViewById(R.id.activity_contentprovider_textview22);
textView33 = findViewById(R.id.activity_contentprovider_textview33);
textView44 = findViewById(R.id.activity_contentprovider_textview44);
textView5 = findViewById(R.id.activity_contentprovider_textview5);
textView1.setOnClickListener(this);
textView2.setOnClickListener(this);
textView3.setOnClickListener(this);
textView4.setOnClickListener(this);
textView11.setOnClickListener(this);
textView22.setOnClickListener(this);
textView33.setOnClickListener(this);
textView44.setOnClickListener(this);
// 设置user表URI
uri_user = Uri.parse("content://com.wjn.mycontentprovider/user");
// 设置job表URI
job_user = Uri.parse("content://com.wjn.mycontentprovider/job");
}
/**
* 各种点击事件的方法
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.activity_contentprovider_textview1://增 user表
insert(1);
break;
case R.id.activity_contentprovider_textview2://删 user表
delete(1);
break;
case R.id.activity_contentprovider_textview3://改 user表
update(1);
break;
case R.id.activity_contentprovider_textview4://查 user表
query(1);
break;
case R.id.activity_contentprovider_textview11://增 job表
insert(2);
break;
case R.id.activity_contentprovider_textview22://删 job表
delete(2);
break;
case R.id.activity_contentprovider_textview33://改 job表
update(2);
break;
case R.id.activity_contentprovider_textview44://查 job表
query(2);
break;
default:
break;
}
}
/**
* 插入数据
*/
private void insert(int mode) {
String name;
String describe;
Uri uri;
if (mode == 1) {
name = "詹姆斯 user表";
describe = "大家好,我是詹姆斯 user表";
uri = uri_user;
} else {
name = "詹姆斯 job表";
describe = "大家好,我是詹姆斯 job表";
uri = job_user;
}
ContentValues values = new ContentValues();
values.put("id", 1);
values.put("name", name);
values.put("describe", describe);
// 获取ContentResolver
ContentResolver resolver = getContentResolver();
// 通过ContentResolver 向ContentProvider中插入数据
resolver.insert(uri, values);
}
/**
* 删除数据
*/
private void delete(int mode) {
Uri uri;
if (mode == 1) {
uri = uri_user;
} else {
uri = job_user;
}
// 获取ContentResolver
ContentResolver resolver = getContentResolver();
// 通过ContentResolver 将ContentProvider中某条数据删除
resolver.delete(uri, "id=1", null);
}
/**
* 修改数据
*/
private void update(int mode) {
String name;
String describe;
Uri uri;
if (mode == 1) {
name = "API修改 user表";
describe = "大家好,我修改成功了 user表";
uri = uri_user;
} else {
name = "API修改 job表";
describe = "大家好,我修改成功了 job表";
uri = job_user;
}
// 获取ContentResolver
ContentResolver resolver = getContentResolver();
//数据集合
ContentValues values = new ContentValues();
values.put("name", name);
values.put("describe", describe);
// 通过ContentResolver 将ContentProvider中某条数据修改
resolver.update(uri, values, "id=1", null);
}
/**
* 查数据
*/
private void query(int mode) {
Uri uri;
if (mode == 1) {
uri = uri_user;
} else {
uri = job_user;
}
// 获取ContentResolver
ContentResolver resolver = getContentResolver();
// 通过ContentResolver 向ContentProvider中查询数据
Cursor cursor = resolver.query(uri, new String[]{"id", "name", "describe"}, null, null, null);
StringBuilder sbBuilder = new StringBuilder();
while (cursor.moveToNext()) {
int id = cursor.getInt(cursor.getColumnIndex("id"));
sbBuilder.append("ID:" + id + "\n");
String name = cursor.getString(cursor.getColumnIndex("name"));
sbBuilder.append("姓名:" + name + "\n");
String describe = cursor.getString(cursor.getColumnIndex("describe"));
sbBuilder.append("描述:" + describe + "\n\n\n");
}
textView5.setText(sbBuilder.toString());
cursor.close();// 关闭游标
}
}
5.结果
user表
“增”——>“查”
“改”——>“查”
“删”——>"查"
job表
增”——>“查”
“改”——>“查”
“删”——>"查"
6.ContentProvider优点
<1> 安全
ContentProvider为应用间的数据交互提供了一个安全的环境:允许把自己的应用数据根据需求开放给 其他应用 进行 增、删、改、查,而不用担心因为直接开放数据库权限而带来的安全问题。
<2> 访问简单高效
对比于其他对外共享数据的方式,数据访问方式会因数据存储的方式而不同
(1) 采用 文件方式 对外共享数据,需要进行文件操作读写数据。
(2) 采用 Sharedpreferences 共享数据,需要使用sharedpreferences API读写数据
(3) 而采用ContentProvider方式,其 解耦了 底层数据的存储方式,使得无论底层数据存储采用何种方式,外界对数据的访问方式都是统一的,这使得访问简单 & 高效 。