应用层
ContentProvider平时使用比较少,今天大概看一下它的使用和简单原理。
通常ContentProvider会结合SQLiteDatabase数据库一起使用。所以我们再构造函数中初始化一个SQLiteDatabase对象。
private SQLiteDatabase sqLiteDatabase;
@Override
public boolean onCreate() {
sqLiteDatabase = new DatabaseHelper(getContext()).getWritableDatabase();
return true;
}
同时,一个数据库可能有多张表,每张表有多行多列,需要使用UriMatcher对Uri进行匹配处理。所以需要一个UriMatcher静态变量。
public static final String AUTHORITIES = "com.one.provider";
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sUriMatcher.addURI(AUTHORITIES, DatabaseHelper.TABLE_NAME, DatabaseHelper.TABLE_CODE);
}
然后,我们的增删查改操作都是依赖SQLiteDatabase实现的。
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Log.d(TAG, "query");
if (sUriMatcher.match(uri) == DatabaseHelper.TABLE_CODE) {
String tableName = DatabaseHelper.TABLE_NAME;
return sqLiteDatabase.query(tableName, projection, selection, selectionArgs, null, null, sortOrder);
} else {
return null;
}
}
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
if (sUriMatcher.match(uri) == DatabaseHelper.TABLE_CODE) {
String tableName = DatabaseHelper.TABLE_NAME;
sqLiteDatabase.insert(tableName, null, contentValues);
return uri;
} else {
return null;
}
}
@Override
public int delete(Uri uri, String selection, String[] args) {
if (sUriMatcher.match(uri) == DatabaseHelper.TABLE_CODE) {
String tableName = DatabaseHelper.TABLE_NAME;
return sqLiteDatabase.delete(tableName, selection, args);
} else {
return -1;
}
}
@Override
public int update(Uri uri, ContentValues contentValues, String selection, String[] args) {
if (sUriMatcher.match(uri) == DatabaseHelper.TABLE_CODE) {
String tableName = DatabaseHelper.TABLE_NAME;
return sqLiteDatabase.update(tableName, contentValues, selection, args);
} else {
return -1;
}
}
而DatabaseHelper主要是帮助我们建表和进行数据库版本控制。
public static final int VERSION = 100;
public static final int TABLE_CODE = 1;
public static final String TABLE_NAME = "firstTable";
public static final String COLUMN_ID = "_id";
public static final String PKG_NAME = "pkgName";
public static final String LAST_TIME = "lastTime";
private static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS "
+ TABLE_NAME
+ " ("
+ COLUMN_ID
+ " INTEGER PRIMARY KEY AUTOINCREMENT, "
+ PKG_NAME
+ " TEXT NOT NULL,"
+ LAST_TIME
+ " LONG"
+ ");";
public DatabaseHelper(Context context) {
super(context, MyProvider.class.getName(), null, VERSION);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(CREATE_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
最后,需要在AndroidManifest进行声明。
<provider
android:authorities="com.one.provider"
android:name="com.one.provider.MyProvider"/>
这里authorities的作用是用于标志唯一的Uri,前面的UriMatcher 就需要根据这个值进行匹配。
完成注册后,我们就可以通过ContentResolver对ContentProvider进行读写了。
首先根据authorities获得Uri对象。
private Uri uri = Uri.parse("content://" + MyProvider.AUTHORITIES + "/" + DatabaseHelper.TABLE_NAME);
首先看下简单的查询操作:
public void query() {
Cursor cursor = mResolver.query(uri, null, null, null);
while (cursor.moveToNext()) {
Log.d(TAG, "query " + cursor.getColumnName(0) + "=" + cursor.getInt(0)
+" " + cursor.getColumnName(1) + "=" + cursor.getString(1)
+ " " + cursor.getColumnName(2) + "=" + cursor.getLong(2));
}
cursor.close();
}
插入操作则需要考虑Primary Key冲突的问题。
public void insert() {
ContentValues values = new ContentValues();
values.put(DatabaseHelper.COLUMN_ID, 101);
values.put(DatabaseHelper.PKG_NAME, mContext.getPackageName());
long lastTime = System.currentTimeMillis();
Log.d(TAG, "lastTime=" + lastTime);
values.put(DatabaseHelper.LAST_TIME, lastTime);
String[] projections = new String[]{DatabaseHelper.COLUMN_ID};
String[] selectionArgs = new String[]{101 + ""};
String selection = DatabaseHelper.COLUMN_ID + " =?";
Cursor cursor = mResolver.query(uri, projections, selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
Log.d(TAG, "update id=" + cursor.getInt(cursor.getColumnIndex(DatabaseHelper.COLUMN_ID)));
String where = DatabaseHelper.COLUMN_ID + "=?";
String[] conditions = new String[]{101 + ""};
int code = mResolver.update(uri, values, where, conditions);
Log.d(TAG, "update code=" + code);
} else {
mResolver.insert(uri, values);
}
cursor.close();
}
最后看一下ContentProvider的启动过程,跟其他组件一样,它也是通过ActivityThread启动的。
启动
查询
参考
理解ContentProvider原理
ContentProvider使用详解
Android:关于ContentProvider的知识都在这里了!