ContentProvider
一、预备知识
uri对象
content://com.example.app.provider/table1
content://com.example.app.provider/table1/1
使用通配符
*
:表示匹配任意长度的任意字符
#
:表示匹配任意长度的数字
uri字符串转uri对象:Uri.parse("字符串")
Cursor对象
常用方法:来自Carson_Ho
c.move(int offset); //以当前位置为参考,移动到指定行
c.moveToFirst(); //移动到第一行
c.moveToLast(); //移动到最后一行
c.moveToPosition(int position); //移动到指定行
c.moveToPrevious(); //移动到前一行
c.moveToNext(); //移动到下一行
c.isFirst(); //是否指向第一条
c.isLast(); //是否指向最后一条
c.isBeforeFirst(); //是否指向第一条之前
c.isAfterLast(); //是否指向最后一条之后
c.isNull(int columnIndex); //指定列是否为空(列基数为0)
c.isClosed(); //游标是否已关闭
c.getCount(); //总数据项数
c.getPosition(); //返回当前游标所指向的行数
c.getColumnIndex(String columnName);//返回某列名对应的列索引值
c.getString(int columnIndex); //返回当前行指定列的值
遍历数据
c.moveToFirst();
while (!c.isAfterLast()) {
int id=result.getInt(c.getColumnIndex("id"));
// ...
c.moveToNext();
}
c.close();
二、提供方Provider
-
写一个ContentProvider的子类,重写方法
- onCreate:初始化一个SQLiteOpenHelper对象,通过getReadableDatabase和getWritableDatabase获得一个SQLiteDatabase对象,用来操作数据库,给下面的方法使用。(此SQLiteOpenHelper对象可以使用内部类方式定义子类)
- query
- insert
- upadte
- delete
- getType:根据uri返回一个MIME
@Override public int delete(Uri uri, String selection, String[] selectionArgs) { SQLiteDatabase db = mDbOpenHelper.getWritableDatabase(); String[] param = matchParam(uri); if (!TextUtils.isEmpty(param[0]) && !TextUtils.isEmpty(param[1])) { return db.delete(param[0], "id=?", new String[]{param[1]}); } else if (TextUtils.isEmpty(param[1])) { return db.delete(param[0], selection, selectionArgs); } return 0; } //用来从uri中判断查询的表,和分离路径参数(路径中的id) private String[] matchParam(Uri uri) { String[] param = new String[]{null, null}; switch (uriMatcher.match(uri)) { case USER_DIR: param[0] = "user"; break; case USER_ITEM: param[0] = "user"; // “/”为分隔符,第一个“/”右边元素下标为0;“//”不算 param[1] = uri.getPathSegments().get(1); break; } return param; } @Override public String getType(@NonNull Uri uri) { switch (uriMatcher.match(uri)) { case USER_DIR: // 多条记录vnd.android.cursor.dir开头 return "vnd.android.cursor.dir/vnd.cn.adolf.db.provider.user"; case USER_ITEM: // 一条记录vnd.android.cursor.item开头 return "vnd.android.cursor.item/vnd.cn.adolf.db.provider.user"; } return null; }
-
在manifest.xml中注册provider
<provider android:name="provider类路径名" android:authorities="一般是 包名.provider" android:enabled="true" android:exported="true" />
github源代码: AdolfDbProvider.java
三、调用方ContentResolver
- 使用
context.getContentResolver();
获得一个ContentResolver对象 - 调用ContentResolver对象的
insert, delete, update, query
- 要传入一个uri:
content://provider注册的authorities/表名/id
可以使用一个Manager来管理ContentResolver对象的调用,用来装配ContentResolver所调用方法的参数
public class DbResolverManager {
private static final String ADOLF_URI = "content://cn.adolf.db.provider/";
private static DbResolverManager instance; // 懒汉,在需要使用时才实例化
// private static DatabaseManager instance= new DatabaseManager(context); // 饿汉,初始化时就实例化
private Context mContext;
private ContentResolver mResolver;
private DbResolverManager(Context context) {
this.mContext = context;
this.mResolver = context.getContentResolver();
}
public static synchronized DbResolverManager getInstance(Context context) {
if (instance == null) {
instance = new DbResolverManager(context);
}
return instance;
}
public Uri addUser(UserBean userBean) {
Uri uri = Uri.parse(ADOLF_URI + "user");
ContentValues values = new ContentValues();
values.put("username", userBean.getUsername());
values.put("sex", userBean.getSex());
values.put("motto", userBean.getMotto() + System.currentTimeMillis());
Uri newUri = mResolver.insert(uri, values);
return newUri;
}
public int deleteUserById(int id) {
if (findUserById(id) == null)
return 0;
Uri uri = Uri.parse(ADOLF_URI + "user/" + id);
int delete = mResolver.delete(uri, null, null);
return delete;
}
public Cursor findUserById(int id) {
Uri uri = Uri.parse(ADOLF_URI + "user/" + id);
Cursor cursor = mResolver.query(uri, null, null, null, null);
return cursor;
}
//...省略其他方法
}