Android四大元件——ContentProvider的增刪改查和優化
阿新 • • 發佈:2019-02-11
前言
ContentProvider步驟:創資料庫,寫規則匹配,配置manifests,另一個應用使用
其實ContentProvider就是:在一個匹配器中寫入自己寫好的匹配規則,並對外提供寫好的匹配規則供使用,剩下的就是增刪改查的處理
細節處理:
在增刪改查中的查詢中,是沒有cursor.getBoolean這個方法的,所以要對資料庫中獲取布林值進行處理:
msg.setFlag(cursor.getInt(cursor.getColumnIndex("flag")) != 0);
ContentProvider的增刪改查
一、建立一個類繼承SQLiteOpenHelper,並用SQL語句建立一個SQLite二、建立一個類繼承ContentProvider,提供增刪改查的方法public class CommonOpenHelper extends SQLiteOpenHelper { private static CommonOpenHelper helper; public static CommonOpenHelper getInstance(Context context) { if (helper == null) { helper = new CommonOpenHelper(context, "common.db", null, 1); } return helper; } private CommonOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table message(" + "id integer primary key autoincrement, " + "content varchar, " + "date varchar " + ")"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
三、在manifests檔案中配置你所寫的ContentProviderpublic class MyMessageProvider extends ContentProvider { //資料庫名 public final static String DB_MESSAGE = "message"; //放置一個數據庫 CommonOpenHelper helper; SQLiteDatabase db; //空白匹配器 UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); //自身的匹配規則 final static int CODE_MESSAGE_INSERT = 0; final static int CODE_MESSAGE_QUERY = 1; final static int CODE_MESSAGE_DELETE = 2; final static int CODE_MESSAGE_UPDATE = 3; //主機名 final static String authority = "com.handsome.nfcc"; final static Uri BASE_URI = Uri.parse("content://com.handsome.nfcc"); //寫入該主機名的匹配規則 { matcher.addURI(authority, "message/insert", CODE_MESSAGE_INSERT); matcher.addURI(authority, "message/query", CODE_MESSAGE_QUERY); matcher.addURI(authority, "message/delete", CODE_MESSAGE_DELETE); matcher.addURI(authority, "message/update", CODE_MESSAGE_UPDATE); } //對外提供的URI public interface URI { Uri CODE_MESSAGE_INSERT = Uri.parse("content://" + authority + "/message/insert"); Uri CODE_MESSAGE_QUERY = Uri.parse("content://" + authority + "/message/query"); Uri CODE_MESSAGE_DELETE = Uri.parse("content://" + authority + "/message/delete"); Uri CODE_MESSAGE_UPDATE = Uri.parse("content://" + authority + "/message/update"); } @Override public boolean onCreate() { helper = CommonOpenHelper.getInstance(getContext()); db = helper.getWritableDatabase(); return false; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { switch (matcher.match(uri)) { case CODE_MESSAGE_QUERY: Cursor cursor = db.query(DB_MESSAGE, projection, selection, selectionArgs, null, null, sortOrder); //註冊內容觀察者,觀察資料變化 cursor.setNotificationUri(getContext().getContentResolver(), BASE_URI); return cursor; default: throw new IllegalArgumentException("未識別的uri" + uri); } } @Override public String getType(Uri uri) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { switch (matcher.match(uri)) { case CODE_MESSAGE_INSERT: long rowId = db.insert(DB_MESSAGE, null, values); if (rowId == -1) { //新增失敗 return null; } else { //傳送內容廣播 getContext().getContentResolver().notifyChange(BASE_URI, null); //新增成功 return ContentUris.withAppendedId(uri, rowId); } default: throw new IllegalArgumentException("未識別的uri" + uri); } } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { switch (matcher.match(uri)) { case CODE_MESSAGE_DELETE: int number = db.delete(DB_MESSAGE, selection, selectionArgs); //傳送內容廣播 getContext().getContentResolver().notifyChange(BASE_URI, null); return number; default: throw new IllegalArgumentException("未識別的uri" + uri); } } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { switch (matcher.match(uri)) { case CODE_MESSAGE_UPDATE: int number = db.update(DB_MESSAGE, values, selection, selectionArgs); //傳送內容廣播 getContext().getContentResolver().notifyChange(BASE_URI, null); return number; default: throw new IllegalArgumentException("未識別的uri" + uri); } } }
<provider
android:name=".Provider.MyMessageProvider"
android:authorities="com.handsome.nfcc" />
四、在另一個應用中寫一個數據庫的增刪改查類,使用該ContentProvider public class MessageDao {
/**
* 新增資料
*/
public static boolean insert(ContentResolver resolver, Message msg) {
ContentValues values = new ContentValues();
values.put("content", msg.getContent());
values.put("date", DateUtils.showDate());
resolver.insert(MyMessageProvider.URI.CODE_MESSAGE_INSERT, values);
return true;
}
/**
* 刪除資料
*/
public static void delete(ContentResolver resolver, int id) {
resolver.delete(MyMessageProvider.URI.CODE_MESSAGE_DELETE, "id = " + id, null);
}
/**
* 刪除全部資料
*/
public static void deleteAll(ContentResolver resolver) {
resolver.delete(MyMessageProvider.URI.CODE_MESSAGE_DELETE, null, null);
}
/**
* 查詢資料
*
* @param resolver
* @return
*/
public static List<Message> query(ContentResolver resolver) {
List<Message> list = new ArrayList<>();
Cursor cursor = resolver.query(MyMessageProvider.URI.CODE_MESSAGE_QUERY, null, null, null, null);
while (cursor.moveToNext()) {
Message msg = new Message();
msg.setDate(cursor.getString(cursor.getColumnIndex("date")));
msg.setContent(cursor.getString(cursor.getColumnIndex("content")));
msg.setId(cursor.getInt(cursor.getColumnIndex("id")));
list.add(0, msg);
}
return list;
}
}
ContentProvider的優化
往往在一個專案中有很多的資料庫,這個時候並不是重複的寫ContentProvider程式碼,而是將所有資料庫中放在一個ContentProvider中,提供一個查詢表名的方法,並對其相應的表進行操作
一、ContentProvider的程式碼優化(一套程式碼適用多個數據庫)
public class MyDataProvider extends ContentProvider {
//資料庫名
public final static String DB_DATA = "data";
public final static String DB_FETCH = "fetch";
public final static String DB_MESSAGE = "message";
//放置一個數據庫
CommonOpenHelper helper;
SQLiteDatabase db;
UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
//自身的匹配規則
final static int CODE_DATA = 0;
final static int CODE_FETCH = 1;
final static int CODE_MESSAGE = 2;
//主機名
final static String authority = "com.handsome.nfc";
final static Uri BASE_URI = Uri.parse("content://com.handsome.nfc");
//寫入該主機名的匹配規則
{
matcher.addURI(authority, "data", CODE_DATA);
matcher.addURI(authority, "fetch", CODE_FETCH);
matcher.addURI(authority, "message", CODE_MESSAGE);
}
//對外提供的URI
public interface URI {
Uri DATA_CONTENT_URI = Uri.parse(BASE_URI + "/data");
Uri FETCH_CONTENT_URI = Uri.parse(BASE_URI + "/fetch");
Uri MESSAGE_CONTENT_URI = Uri.parse(BASE_URI + "/message");
}
/**
* 獲取資料庫表名
*
* @param uri
* @return
*/
private String getTableName(Uri uri) {
String tableName = null;
switch (matcher.match(uri)) {
case CODE_DATA:
tableName = DB_DATA;
break;
case CODE_FETCH:
tableName = DB_FETCH;
break;
case CODE_MESSAGE:
tableName = DB_MESSAGE;
break;
default:
break;
}
return tableName;
}
@Override
public boolean onCreate() {
helper = CommonOpenHelper.getInstance(getContext());
db = helper.getWritableDatabase();
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
String tableName = getTableName(uri);
if (tableName == null) {
throw new IllegalArgumentException("非法Uri:" + uri);
}
Cursor cursor = db.query(tableName, projection, selection, selectionArgs, null, null, sortOrder);
//註冊內容觀察者,觀察資料變化
cursor.setNotificationUri(getContext().getContentResolver(), BASE_URI);
return cursor;
}
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
String tableName = getTableName(uri);
if (tableName == null) {
throw new IllegalArgumentException("非法Uri:" + uri);
}
long rowId = db.insert(tableName, null, values);
if (rowId == -1) {
return null;
} else {
//傳送內容廣播
getContext().getContentResolver().notifyChange(BASE_URI, null);
return ContentUris.withAppendedId(uri, rowId);
}
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
String tableName = getTableName(uri);
if (tableName == null) {
throw new IllegalArgumentException("非法Uri:" + uri);
}
int number = db.delete(tableName, selection, selectionArgs);
//傳送內容廣播
getContext().getContentResolver().notifyChange(BASE_URI, null);
return number;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
String tableName = getTableName(uri);
if (tableName == null) {
throw new IllegalArgumentException("非法Uri:" + uri);
}
int number = db.update(tableName, values, selection, selectionArgs);
//傳送內容廣播
getContext().getContentResolver().notifyChange(BASE_URI, null);
return number;
}
}
二、在各個不同的資料庫中的使用
Data資料庫通過名字查詢示例
private static boolean queryDataByName(ContentResolver resolver, String tag_id) {
Cursor cursor = resolver.query(MyDataProvider.URI.DATA_CONTENT_URI, null, "tag_id = '" + tag_id + "'", null, null);
if (cursor.moveToFirst()) {
return true;
}
return false;
}
Fetch資料庫插入示例public static boolean insert(ContentResolver resolver, Fetch fetch) {
ContentValues values = new ContentValues();
values.put("fetch_num", fetch.getFetch_num());
values.put("username", fetch.getUsername());
values.put("installationId", fetch.getInstallationId());
values.put("created", fetch.getCreated());
values.put("date", System.currentTimeMillis());
resolver.insert(MyDataProvider.URI.FETCH_CONTENT_URI, values);
return true;
}
Message資料庫查詢示例 public static List<Message> query(ContentResolver resolver) {
List<Message> list = new ArrayList<>();
Cursor cursor = resolver.query(MyDataProvider.URI.MESSAGE_CONTENT_URI, null, null, null, null);
while (cursor.moveToNext()) {
Message msg = new Message();
msg.setDate(cursor.getString(cursor.getColumnIndex("date")));
msg.setContent(cursor.getString(cursor.getColumnIndex("content")));
msg.setId(cursor.getInt(cursor.getColumnIndex("id")));
list.add(0, msg);
}
return list;
}