作为四大组件之一,ContentProvider 算是我直接使用次数最少的一个了。主要提供应用程序之间共享数据的接口
一、创建ContentProvider 实例
ContentProvider是一个抽象类。创建MyProvider类继承ContentProvider,实现6个抽象方法:onCreate
、getType
、query
、insert
、delete
、update
。
onCreate()方法会在创建的时候调用一次。其它方法通过ContentResolver
的增删改查方法触发。
所以我们只需要在对应的方法下对数据库进行增删改查就行了。
public class MyProvider extends ContentProvider {
private static final String TAG = "MyProvider";
@Override
public boolean onCreate() {
Log.d(TAG, "onCreate, Thread:" + Thread.currentThread().getName());
return false;
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
Log.d(TAG, "getType, Thread:" + Thread.currentThread().getName());
return null;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
Log.d(TAG, "query, Thread:" + Thread.currentThread().getName());
return SqlHelper.getInstance().query(TeacherTable.TABLE_NAME, projection, selection, selectionArgs);
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
Log.d(TAG, "insert, Thread:" + Thread.currentThread().getName());
SqlHelper.getInstance().insert(TeacherTable.TABLE_NAME, values);
return null;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
Log.d(TAG, "delete, Thread:" + Thread.currentThread().getName());
SqlHelper.getInstance().delete(TeacherTable.TABLE_NAME, selection, selectionArgs);
return 0;
}
@Override
public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
Log.d(TAG, "update, Thread:" + Thread.currentThread().getName());
SqlHelper.getInstance().update(TeacherTable.TABLE_NAME, values, selection, selectionArgs);
return 0;
}
}
二、注册ContentProvider
<provider
android:authorities="test.com.provider.MyProvider"
android:name=".provider.MyProvider"
// android:process=":provider"
// android:permission="com.zy.android.PROVIDER"
/>
- authorities : 是ContentProvider 的唯一标识,所以最好加上包名前缀
- name : 需要注册的ContentProvider 名
三、使用
1、插入:
Uri uri = Uri.parse("content://test.com.provider.MyProvider");
ContentValues values = new ContentValues();
values.put(TeacherTable.COLUMN_NAME, "张三");
values.put(TeacherTable.COLUMN_GRADE,"1");
values.put(TeacherTable.COLUMN_CLS,"3");
values.put(TeacherTable.COLUMN_ID, id);
getContentResolver().insert(uri,values);
在Uri 中指明ContentProvider 的标识,也就是注册的authorities
属性值。
固定写法:Uri.parse("content://authorities")
通过getContentResolver()
获得ContentResolver
对象。
2、删除
getContentResolver().delete(uri, "name = ?", new String[]{"张三"});
3、修改
ContentValues values2 = new ContentValues();
values2.put(TeacherTable.COLUMN_NAME, "王二麻子");
values2.put(TeacherTable.COLUMN_GRADE,"1");
values2.put(TeacherTable.COLUMN_CLS,"3");
//values.put(TeacherTable.COLUMN_ID, id);
getContentResolver().update(uri, values2, "name = ? ", new String[]{"张三"});
将张三修改成王二麻子
4、查询
Cursor cursor = getContentResolver().query(uri, null, "name = ? ", new String[]{"张三"}, "1");
查询操作会返回一个Cursor
对象,通过对Cursor 操作,获得值。
if (cursor == null){
return;
}
cursor.moveToFirst();
StringBuffer sb = new StringBuffer();
while (!cursor.isAfterLast()){
sb.append("ID:" + cursor.getInt(cursor.getColumnIndex(TeacherTable.COLUMN_ID))
+ " name:" + cursor.getString(cursor.getColumnIndex(TeacherTable.COLUMN_NAME))
+ " grade:"+ cursor.getString(cursor.getColumnIndex(TeacherTable.COLUMN_GRADE))
+ " cls: " + cursor.getString(cursor.getColumnIndex(TeacherTable.COLUMN_CLS))
+ "\n"
);
cursor.moveToNext();
}
cursor.close();
ContentProvider的query
方法需要返回Cursor 才行,否则获得的是一个空对象。
TeacherTable表结构
public class TeacherTable {
//表名
public static final String TABLE_NAME = "teacher";
//列
public static final String COLUMN_ID = "id";
public static final String COLUMN_NAME = "name";
public static final String COLUMN_GRADE = "grade";
public static final String COLUMN_CLS = "cls";
//创建teacher表
public static final String CREATE_TABLE = "CREATE TABLE " //"CREATE TABLE IF NOT EXISTS "
+ TABLE_NAME + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_NAME + " TEXT,"
+ COLUMN_GRADE + " TEXT,"
+ COLUMN_CLS + " TEXT"
+ ")";
private int id;
private String name;
private String grade;
private String cls;
}
SqlHelper
/**
* Created by zy
* date 2019/12/24 0024.
* desc:
*/
public class SqlHelper extends SQLiteOpenHelper {
//数据库名
private static final String DB_NAME = "test_db";
//数据库版本
private static final int DB_VERSION = 1;
public static SqlHelper instance;
public static SqlHelper getInstance(){
if (instance == null){
instance = new SqlHelper(MyApp.context);
}
return instance;
}
/**
* @param context 上下文
* 数据库名称
* 数据库游标工厂类(可选)
* 数据库版本
*/
public SqlHelper(@Nullable Context context) {
super(context, DB_NAME, null, DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
//创建教师表
db.execSQL(TeacherTable.CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String drop = "DROP TABLE IF EXISTS ";
//drop older table existed
db.execSQL(drop + TeacherTable.TABLE_NAME);
onCreate(db);
}
/**
* 插入
*
* @param tableName 表名
* @param values
* @return 插入是否成功
*/
public boolean insert(String tableName, ContentValues values) {
SQLiteDatabase db = this.getWritableDatabase();
long res = db.insert(tableName, null, values);
return res != -1;
}
/**
* 根据条件删除
* @param tableName
* @param where
* @param args
* @return
*/
public boolean delete(String tableName, String where, String[] args) {
try {
SQLiteDatabase db = this.getWritableDatabase();
db.delete(tableName, where, args);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 修改
* @param tableName
* @param id
* @param values
* @return
*/
public boolean update(String tableName, String id, ContentValues values) {
try {
SQLiteDatabase db = this.getWritableDatabase();
db.update(tableName, values, TeacherTable.COLUMN_ID + " = ? ", new String[]{id});
return true;
} catch (Exception e) {
e.printStackTrace();
Log.e("tag","update Exception: " + e.toString());
}
return false;
}
/**
* 更新
* @param tableName
* @param values
* @param selection
* @param selectionArgs
*/
public void update(String tableName, ContentValues values, String selection, String[] selectionArgs){
SQLiteDatabase db = this.getWritableDatabase();
db.update(tableName, values, selection, selectionArgs);
}
/**
* 查询
* @param tableName
* @param columns
* @param selection
* @param selectionArgs
* @return
*/
public Cursor query(String tableName, String[] columns, String selection, String[] selectionArgs) {
try {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(tableName, columns, selection, selectionArgs, null, null, null);
return cursor;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
总结
关于SQLite
使用,可以看我的另一篇文字:Android SQLite简单使用
因为四大组件中ContentProvider主动使用频率比较低,所以没有去过多深入了解,只是记录使用方式。
其它三大组件工作流程: