ContentObserver——内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObserver也分为“表“ContentObserver、“行”ContentObserver,当然这是与它所监听的Uri MIME Type有关的。
public class ContactsContentProvider extends ContentProvider{ @Override public boolean onCreate() { // TODO Auto-generated method stub return false; } @Override public int delete(Uri arg0, String arg1, String[] arg2) { // TODO Auto-generated method stub return 0; } @Override public String getType(Uri arg0) { // TODO Auto-generated method stub return null; } @Override public Uri insert(Uri arg0, ContentValues arg1) { // TODO Auto-generated method stub return null; } @Override public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3, String arg4) { // TODO Auto-generated method stub return null; } @Override public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) { // TODO Auto-generated method stub return 0; } }
public class ProviderMetaData { public static final String AUTHORITY = "com.johnny.contactsprovider"; public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY); public static final class ContactsData implements BaseColumns{ public static final String TABLE_NAME = "contacts"; public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, TABLE_NAME); public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact"; public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact"; public static final String CONTACT_NAME = "name"; public static final String CONTACT_TELEPHONE = "telephone"; public static final String CONTACT_CREATE_DATE = "create_date"; public static final String CONTACT_CONTENT = "content"; public static final String CONTACT_GROUP = "group_name"; public static final String DEFAULT_ORDERBY = "create_date DESC"; public static final String SQL_CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + _ID + " INTEGER PRIMARY KEY," + CONTACT_NAME + " VARCHAR(50)," + CONTACT_TELEPHONE + " VARCHAR(11)," + CONTACT_CONTENT +" TEXT," + CONTACT_CREATE_DATE + " INTEGER" + ");" ; } }
static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); static final HashMap<String, String> CONTACTS_PROJECTION_MAP = new HashMap<String, String>(); private static final int CONTACTS = 1; private static final int CONTACTS_ID = 2; static{ final UriMatcher matcher = URI_MATCHER; matcher.addURI(ProviderMetaData.AUTHORITY, "contacts", CONTACTS); matcher.addURI(ProviderMetaData.AUTHORITY, "contacts/#", CONTACTS_ID); HashMap<String, String> map = CONTACTS_PROJECTION_MAP; map.put(ContactsData._ID, ContactsData._ID); map.put(ContactsData.CONTACT_NAME, ContactsData.CONTACT_NAME); map.put(ContactsData.CONTACT_TELEPHONE, ContactsData.CONTACT_TELEPHONE); map.put(ContactsData.CONTACT_CONTENT, ContactsData.CONTACT_CONTENT); map.put(ContactsData.CONTACT_CREATE_DATE, ContactsData.CONTACT_CREATE_DATE); }
private class DatabaseHelper extends SQLiteOpenHelper{ static final String DATABASE_NAME = "test.db"; static final int DATABASE_VERSION = 1; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub db.execSQL(ContactsData.SQL_CREATE_TABLE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub onCreate(db); } }
@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // TODO Auto-generated method stub SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder(); switch(URI_MATCHER.match(uri)){ case CONTACTS_ID: queryBuilder.setTables(ContactsData.TABLE_NAME); queryBuilder.setProjectionMap(CONTACTS_PROJECTION_MAP); queryBuilder.appendWhere(ContactsData.TABLE_NAME + "._id="+Long.toString(ContentUris.parseId(uri))); break; case CONTACTS: queryBuilder.setTables(ContactsData.TABLE_NAME); queryBuilder.setProjectionMap(CONTACTS_PROJECTION_MAP); break; } String orderBy; if(TextUtils.isEmpty(sortOrder)) { orderBy = ContactsData.DEFAULT_ORDERBY; } else { orderBy = sortOrder; } SQLiteDatabase db = mDbHelper.getReadableDatabase(); Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, orderBy); return cursor; }
@Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub SQLiteDatabase db = mDbHelper.getWritableDatabase(); long id = db.insertOrThrow(ContactsData.TABLE_NAME, null, values); // 更新数据时,通知其他ContentObserver getContext().getContentResolver().notifyChange(ContactsData.CONTENT_URI, null); if(id > 0){ return ContentUris.withAppendedId(uri, id); } return null; }
@Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub SQLiteDatabase db = mDbHelper.getWritableDatabase(); int modified = 0; switch(URI_MATCHER.match(uri)){ case CONTACTS_ID: selection = DatabaseUtils.concatenateWhere(selection,ContactsData.TABLE_NAME + "._id=?"); selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs, new String[]{Long.toString(ContentUris.parseId(uri))}); Log.d("Test", "selectionArgs 0"+selectionArgs); modified = db.update(ContactsData.TABLE_NAME, values, selection, selectionArgs); break; case CONTACTS: modified = db.update(ContactsData.TABLE_NAME, values, selection, selectionArgs); Log.d("Test", "selectionArgs 1"+selectionArgs); break; } // 更新数据时,通知其他ContentObserver getContext().getContentResolver().notifyChange(ContactsData.CONTENT_URI, null); return modified; }
@Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub SQLiteDatabase db = mDbHelper.getWritableDatabase(); int deleted = 0; switch(URI_MATCHER.match(uri)){ case CONTACTS_ID: selection = DatabaseUtils.concatenateWhere(selection,ContactsData.TABLE_NAME + "._id=?"); selectionArgs = DatabaseUtils.appendSelectionArgs(selectionArgs, new String[]{Long.toString(ContentUris.parseId(uri))}); Log.d("Test", "selectionArgs 0"+selectionArgs); deleted = db.delete(ContactsData.TABLE_NAME, selection, selectionArgs); break; case CONTACTS: deleted = db.delete(ContactsData.TABLE_NAME, selection, selectionArgs); Log.d("Test", "selectionArgs 1"+selectionArgs); break; } // 更新数据时,通知其他ContentObserver getContext().getContentResolver().notifyChange(ContactsData.CONTENT_URI, null); return deleted; }
@Override public String getType(Uri uri) { // TODO Auto-generated method stub switch(URI_MATCHER.match(uri)){ case CONTACTS: return ContactsData.CONTENT_TYPE; case CONTACTS_ID: return ContactsData.CONTENT_ITEM_TYPE; // default: // throw new IllegalArgumentException("Unknow URI: " + uri); } return null; }
<provider android:name="com.johnny.testcontentprovider.ContactsContentProvider" android:authorities="com.johnny.contactsprovider"> </provider>
private void insertContact1(){ ContentValues values = new ContentValues(); values.put(ContactsData.CONTACT_NAME, "James"); values.put(ContactsData.CONTACT_TELEPHONE, "18888888888"); values.put(ContactsData.CONTACT_CONTENT, "NBA Star"); values.put(ContactsData.CONTACT_CREATE_DATE, System.currentTimeMillis()); Uri uri = getContentResolver().insert(ContactsData.CONTENT_URI, values); Log.d("Test", "uri = "+uri); } private void deleteContact1(){ int count = getContentResolver().delete(ContactsData.CONTENT_URI, ContactsData.CONTACT_NAME+"='James'", null); Log.d("Test", "count = "+count); } private void updateContact1(){ ContentValues values = new ContentValues(); values.put(ContactsData.CONTACT_TELEPHONE, "16666666666"); int count = getContentResolver().update(ContactsData.CONTENT_URI,values, ContactsData.CONTACT_NAME+"='James'", null); Log.d("Test", "count = "+count); } private void updateContact1ID(){ ContentValues values = new ContentValues(); values.put(ContactsData.CONTACT_TELEPHONE, "17777777"); int count = getContentResolver().update(ContentUris.withAppendedId(ContactsData.CONTENT_URI,2),values, null, null); Log.d("Test", "count = "+count); } private void queryContact1(){ //Cursor cursor = this.getContentResolver().query(ContactsData.CONTENT_URI, null, ContactsData.CONTACT_NAME+"='James'", null, null); Cursor cursor = this.getContentResolver().query(ContactsData.CONTENT_URI, null, ContactsData.CONTACT_NAME+"=?", new String [] {"James"}, null); Log.e("test ", "count=" + cursor.getCount()); cursor.moveToFirst(); while(!cursor.isAfterLast()) { String name = cursor.getString(cursor.getColumnIndex(ContactsData.CONTACT_NAME)); String telephone = cursor.getString(cursor.getColumnIndex(ContactsData.CONTACT_TELEPHONE)); long createDate = cursor.getLong(cursor.getColumnIndex(ContactsData.CONTACT_CREATE_DATE)); Log.e("Test", "name: " + name); Log.e("Test", "telephone: " + telephone); Log.e("Test", "date: " + createDate); cursor.moveToNext(); } cursor.close(); }
在插入两个数据后分别执行updateContact1()和updateContact1ID()函数,你会发现他们两个分别执行了ContactsContentProvider.update的两个不同地方:分别为case CONTACTS:和case CONTACTS_ID:,现在可以理解
matcher.addURI(ProviderMetaData.AUTHORITY, "contacts", CONTACTS); matcher.addURI(ProviderMetaData.AUTHORITY, "contacts/#", CONTACTS_ID);的不同含义了吧?
(13)创建数据库监听器ContentObserver
在MainActivity中加入以下代码:private ContentObserver mContentObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange) { // TODO Auto-generated method stub Log.d("Test", "mContentObserver onChange"); super.onChange(selfChange); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()).commit(); } getContentResolver().registerContentObserver(ContactsData.CONTENT_URI, true, mContentObserver); }
private class DatabaseHelper extends SQLiteOpenHelper{ static final String DATABASE_NAME = "test.db"; static final int DATABASE_VERSION = 2; public DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub db.execSQL(ContactsData.SQL_CREATE_TABLE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub Log.d("Test", "onUpgrade oldVersion = "+oldVersion+", newVersion = "+newVersion); //onCreate(db); for(int i = oldVersion+1;i <= newVersion;i++){ switch(i){ case 2: db.execSQL("ALTER TABLE " + ContactsData.TABLE_NAME + " ADD COLUMN " + ContactsData.CONTACT_GROUP + " TEXT"); break; } } } }
也要记得要对onCreate做相应的修改,是用户清除数据时重新建表是也会生效
public static final String SQL_CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + _ID + " INTEGER PRIMARY KEY," + CONTACT_NAME + " VARCHAR(50)," + CONTACT_TELEPHONE + " VARCHAR(11)," + CONTACT_CONTENT +" TEXT," + CONTACT_CREATE_DATE + " INTEGER," + CONTACT_GROUP + " TEXT" + ");" ;
下面是升级前后数据库的结果:
用下面代码为DATABASE_VERSION = 2的数据库中的James设在组别和加入Howard联系人:
private void modifyContact1(){ ContentValues values = new ContentValues(); values.put(ContactsData.CONTACT_GROUP, "Miami"); int count = getContentResolver().update(ContactsData.CONTENT_URI,values, ContactsData.CONTACT_NAME+"='James'", null); Log.d("Test", "count = "+count); } private void insertContact2(){ ContentValues values = new ContentValues(); values.put(ContactsData.CONTACT_NAME, "Howard"); values.put(ContactsData.CONTACT_TELEPHONE, "13333333333"); values.put(ContactsData.CONTACT_CONTENT, "NBA Star"); values.put(ContactsData.CONTACT_GROUP, "Rockets"); values.put(ContactsData.CONTACT_CREATE_DATE, System.currentTimeMillis()); Uri uri = getContentResolver().insert(ContactsData.CONTENT_URI, values); Log.d("Test", "uri = "+uri); } private void queryContacts1(){ Cursor cursor = this.getContentResolver().query(ContactsData.CONTENT_URI, null, ContactsData.CONTACT_GROUP+" IN ('Miami','Rockets')", null, null); Log.e("Test ", "count=" + cursor.getCount()); cursor.moveToFirst(); while(!cursor.isAfterLast()) { String name = cursor.getString(cursor.getColumnIndex(ContactsData.CONTACT_NAME)); String telephone = cursor.getString(cursor.getColumnIndex(ContactsData.CONTACT_TELEPHONE)); long createDate = cursor.getLong(cursor.getColumnIndex(ContactsData.CONTACT_CREATE_DATE)); Log.e("Test", "name: " + name); Log.e("Test", "telephone: " + telephone); Log.e("Test", "date: " + createDate); cursor.moveToNext(); } cursor.close(); }
参考:http://codingnow.cn/android/1078.html