上一篇博客主要讲解了下在我们程序中ContentProvider的创建过程。在上一篇博客有上传2份代码分别为testContentProvider(创建ContentProvider的程序),testZSGC调用testContentProvider里面的ContentProvider的程序。当testContentProvider中数据库数据有变化时,如何能够通知到testZSGC这个程序呢?其实android已经为我们提供了监测这变化的功能,那就是ContentObserver,称之为内容观察者。具体使用方法有如下几个步骤,可以下载代码结合阅读:
1:创建一个类继承至ContentObserver,并实现onChange函数。每当有数据变化时就会触发onChange函数。
class MyObserver extends ContentObserver {
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
handler.obtainMessage(LISTENER_TYPE).sendToTarget();
}
}
2:在ContentProvider的增删改查函数值添加如下代码:
this.getContext().getContentResolver().notifyChange(mUri, null);
//notifyChange第一个参数就是我们访问ContentProvider的uri路径
3:在创建Activity时注册ContentObserver
mContext.getContentResolver().registerContentObserver(mUri, true, mObserver);
//mObserver就是步骤1中的MyObserver对象,mUri就是我们访问ContentProvider的uri路径
4:在退出Activity时注销ContentObserver
mContext.getContentResolver().unregisterContentObserver(mObserver);
5:通过上面几步,每当ContentProvider数据有变化时,就会触发步骤1中的onChange函数,然后我们回调至我们的Activity中做出相应的处理。
ObserverHandler.java代码
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
public class ObserverHandler {
private onDataChangeListener mListener;
private int LISTENER_TYPE = 0;
private Uri mUri;
private Context mContext;
private MyObserver mObserver;
public interface onDataChangeListener {
public void onChange(Uri uri);
public Context getContext();
}
public ObserverHandler(Uri uri,onDataChangeListener listener)
{
mListener = listener;
mUri = uri;
mContext = mListener.getContext();
}
public void registerObserver()
{
mObserver = new MyObserver(handler);
mContext.getContentResolver().registerContentObserver(mUri, true, mObserver);
}
public void unRegisterObserver()
{
mContext.getContentResolver().unregisterContentObserver(mObserver);
}
public Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(msg.what == LISTENER_TYPE)
{
mListener.onChange(mUri);
}
}
};
class MyObserver extends ContentObserver {
public MyObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
handler.obtainMessage(LISTENER_TYPE).sendToTarget();
}
}
}
MainActivity.java代码
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import com.example.testzsgc.ObserverHandler.onDataChangeListener;
public class MainActivity extends Activity implements onDataChangeListener{
Uri mUri_insert = Uri.parse("content://com.example.testcontentprovider/test");
Uri mUris_del = Uri.parse("content://com.example.testcontentprovider/test/1"); //删除id为1的数据
Uri mUris_query = Uri.parse("content://com.example.testcontentprovider/test/2"); //查询id为2的数据
Uri mUris_update = Uri.parse("content://com.example.testcontentprovider/test/3"); //修改id为2的数据
private ObserverHandler mObserverHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mObserverHandler = new ObserverHandler(mUri_insert,this);
mObserverHandler.registerObserver();
}
public void insert(View v)
{
ContentResolver cr = this.getContentResolver();
ContentValues value = new ContentValues();
value.put("name", "test1");
Uri uri = cr.insert(mUri_insert, value);
}
public void delete(View v)
{
ContentResolver cr = this.getContentResolver();
int m = cr.delete(mUris_del, null, null);
}
public void query(View v)
{
ContentResolver cr = this.getContentResolver();
Cursor c= cr.query(mUris_query, null, null, null, null);
if(c.moveToFirst() == false)
{
return;
}
int nameindex = c.getColumnIndex("name");
String strname = c.getString(nameindex);
Toast.makeText(this, strname, Toast.LENGTH_SHORT).show();
c.close();
}
public void modify(View v)
{
ContentResolver cr = this.getContentResolver();
ContentValues value = new ContentValues();
value.put("name", "testupdate");
cr.update(mUris_update, value, null, null);
}
@Override
public void onChange(Uri uri) {
Toast.makeText(this, "uri有改变", Toast.LENGTH_SHORT).show();
}
@Override
public Context getContext() {
// TODO Auto-generated method stub
return this;
}
@Override
public void onDestroy()
{
super.onDestroy();
mObserverHandler.unRegisterObserver();
}
}
MycontentProvider.java代码
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.text.TextUtils;
public class MyContentProvider extends ContentProvider{
private SqliteHelper mHelper;
private static final UriMatcher uriMatcher;
public static final String strUri = "com.example.testcontentprovider";
private static final int TEST = 101;
private static final int TESTS = 102;
public static final String CONTENT_TYPE = "vnd.android.cursor.dir/com.example.testcontentproviders";
public static final String CONTENT_TYPE_ITEM = "vnd.android.cursor.item/com.example.testcontentprovider";
Uri mUri = Uri.parse("content://com.example.testcontentprovider/test");
static
{
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(strUri, "test", TESTS);
uriMatcher.addURI(strUri, "test/#", TEST);
}
@Override
public boolean onCreate() {
mHelper = new SqliteHelper(getContext());
return false;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = mHelper.getReadableDatabase();
switch(uriMatcher.match(uri))
{
case TEST:
long id = ContentUris.parseId(uri);
String where = "id="+id;
where += !TextUtils.isEmpty(selection) ? " and (" + selection + ")" : "";// 把其它条件附加上
this.getContext().getContentResolver().notifyChange(mUri, null);
return db.query(SqliteHelper.DB_TABLE, projection, where, selectionArgs, null, null, sortOrder);
case TESTS:
this.getContext().getContentResolver().notifyChange(mUri, null);
return db.query(SqliteHelper.DB_TABLE, projection, selection, selectionArgs, null, null, sortOrder);
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public String getType(Uri uri) {
switch(uriMatcher.match(uri))
{
case TEST:
return CONTENT_TYPE_ITEM;
case TESTS:
return CONTENT_TYPE;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
}
@Override
public Uri insert(Uri uri, ContentValues initvalues) {
SQLiteDatabase db = mHelper.getWritableDatabase();
ContentValues values;
if(initvalues != null)
{
values = new ContentValues(initvalues);
}else
{
values = new ContentValues();
}
switch( uriMatcher.match(uri))
{
case TEST:
break;
case TESTS:
if(values.containsKey(SqliteHelper.DB_TABLE_NAME) == false)
{
values.put(SqliteHelper.DB_TABLE_NAME, "");
}
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
long rowid = db.insert(SqliteHelper.DB_TABLE, null, values); // 返回的是记录的行号,主键为int,实际上就是主键值
if(rowid > 0)
{
Uri noteuri = ContentUris.withAppendedId(uri, rowid);
this.getContext().getContentResolver().notifyChange(mUri, null);
return noteuri;
}
throw new SQLException("Failed to insert row into " + uri);
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = mHelper.getWritableDatabase();
int count = 0;
switch( uriMatcher.match(uri))
{
case TEST: //删除指定数据
long id = ContentUris.parseId(uri);
String where = "id="+id;
where += !TextUtils.isEmpty(selection)?" and ("+selection+")" : "";
count = db.delete(SqliteHelper.DB_TABLE, where, selectionArgs);
break;
case TESTS: //删除所有数据
count = db.delete(SqliteHelper.DB_TABLE, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
this.getContext().getContentResolver().notifyChange(mUri, null);
db.close();
return count;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = mHelper.getWritableDatabase();
int count = 0;
switch( uriMatcher.match(uri))
{
case TEST:
long id = ContentUris.parseId(uri);
String where = "id="+id;
where += !TextUtils.isEmpty(selection)?" and ("+selection+")" : "";
count = db.update(SqliteHelper.DB_TABLE,values, where, selectionArgs);
break;
case TESTS:
db.update(SqliteHelper.DB_TABLE, values, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
this.getContext().getContentResolver().notifyChange(mUri, null);
db.close();
return count;
}
}
class SqliteHelper extends SQLiteOpenHelper{
public final static String DB_NAME = android.os.Environment.getExternalStorageDirectory().getAbsolutePath()+"/test.db";
public final static int DB_VERSION = 1;
public final static String DB_ID = "id";
public final static String DB_TABLE = "test";
public final static String DB_TABLE_NAME = "name";
public SqliteHelper(Context context)
{
super(context,DB_NAME,null,DB_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DB_TABLE + " ("
+ DB_ID + " INTEGER PRIMARY KEY,"
+ DB_TABLE_NAME + " TEXT"
+ ");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS "+DB_TABLE);
onCreate(db);
}
}
源码下载
ContentProvider 实例详解一(创建一个自己的ContentProvider)
ContentProvider 实例详解二(观察者模式监测数据的变化)