在android中经常会用到改变数据库内容后再去使用数据库更新的内容,很多人会重新去query一遍,但是这样的问题就是程序会特别占内存,而且有可能会搂关cursor而导致程序内存未释放等等。其实android内部提供了一种ContentObserver的东西来监听数据库内容的变化。
ContentObserver的构造函数需要一个参数Hanlder,因为ContentObserver内部使用了一个实现Runnable接口的内部类NotificationRunnable,来实现数据库内容的变化。需要使用hanlder去post消息。注册ContentObserver的方法是:getContentResolver().registerContentObserver(uri, notifyForDescendents, observer).
上面3个参数为:
uri----Uri类型,是需要监听的数据库的uri.
notifyForDescendents---boolean true的话就会监听所有与此uri相关的uri。false的话则是直接特殊的uri才会监听。一般都设置为true.
observer-----ContentObserver 就是需要的contentobserver.
初始化一个ContentObserver对象,重载onChange(boolean ),在这个方法里去操作数据库的使用,针对变化后的使用。
写了一个小demo,可以参考下。提示这种监听方式必须是contentprovider才能使用,因为contentprovider有uri.简单的那种sqlite数据库没有uri是使用不了的。
下面demo操作的是在一个activityA里点击button跳转至另外一个activityB,在B中点击button往数据库中加数据,加完后关闭B回到A。A的button的文字自动变化设置到数据库中的字符串。
package ty.com.lto;
import android.app.Activity;
import android.content.Intent;
import android.database.ContentObserver;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
public class ListenDataTest extends Activity{
private Button testBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listen_data_test);
getContentResolver().registerContentObserver(DataChangeProvider.CONTENT_URI,
true, cob);
testBtn = (Button)findViewById(R.id.test_btn);
testBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Intent in = new Intent(ListenDataTest.this,DataChangeTest.class);
startActivity(in);
}
});
}
private ContentObserver cob = new ContentObserver(new Handler()) {
@Override
public boolean deliverSelfNotifications() {
return super.deliverSelfNotifications();
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
testBtn.setText(DataUtils.getChangeName(getApplicationContext()));
}
};
@Override
protected void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(cob);
}
}
package ty.com.lto;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.ContentObservable;
import android.database.ContentObserver;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.Button;
public class DataChangeTest extends Activity{
private Button dataBtn;
DataSqlite mDataSqlite;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.data_change_test);
dataBtn = (Button)findViewById(R.id.data_test_btn);
mDataSqlite = new DataSqlite(this);
dataBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
ContentValues con = new ContentValues();
con.put("name", "数据变化了");
getContentResolver().insert(DataChangeProvider.CONTENT_URI, con);
finish();
}
});
}
}
package ty.com.lto;
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.database.sqlite.SQLiteQueryBuilder;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.net.Uri;
import android.text.TextUtils;
public class DataChangeProvider extends ContentProvider{
private SQLiteOpenHelper mOpenHelper;
private static final int ALARMS = 1;
private static final int ALARMS_ID = 2;
private static final UriMatcher sURLMatcher = new UriMatcher(UriMatcher.NO_MATCH);
public static final Uri CONTENT_URI = Uri.parse("content://ty.com.lto/test");
static {
sURLMatcher.addURI("ty.com.lto", "test", ALARMS);
sURLMatcher.addURI("ty.com.lto", "test/#", ALARMS_ID);
}
private static class DatabaseHelper extends SQLiteOpenHelper{
private static final String TEST_DATABASE = "test.db";
private static final int VERSION = 1;
public DatabaseHelper(Context context) {
super(context, TEST_DATABASE, null, VERSION);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "CREATE TABLE "+"test"+" (" +
"_id INTEGER PRIMARY KEY," +
"name TEXT "+
");";
db.execSQL(sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String sql = "DROP TABLE IF EXIST "+TEST_DATABASE;
db.execSQL(sql);
onCreate(db);
}
}
public DataChangeProvider() {
}
@Override
public int delete(Uri url, String where, String[] whereArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
int count;
long rowId = 0;
switch (sURLMatcher.match(url)) {
case ALARMS:
count = db.delete("test", where, whereArgs);
break;
case ALARMS_ID:
String segment = url.getPathSegments().get(1);
rowId = Long.parseLong(segment);
if (TextUtils.isEmpty(where)) {
where = "_id=" + segment;
} else {
where = "_id=" + segment + " AND (" + where + ")";
}
count = db.delete("test", where, whereArgs);
break;
default:
throw new IllegalArgumentException("Cannot delete from URL: " + url);
}
getContext().getContentResolver().notifyChange(url, null);
return count;
}
@Override
public String getType(Uri url) {
int match = sURLMatcher.match(url);
switch (match) {
case ALARMS:
return "vnd.android.cursor.dir/alarms";
case ALARMS_ID:
return "vnd.android.cursor.item/alarms";
default:
throw new IllegalArgumentException("Unknown URL");
}
}
@Override
public Uri insert(Uri url, ContentValues initialValues) {
if (sURLMatcher.match(url) != ALARMS) {
throw new IllegalArgumentException("Cannot insert into URL: " + url);
}
ContentValues values;
if (initialValues != null) {
values = new ContentValues(initialValues);
} else {
values = new ContentValues();
}
if (!values.containsKey("name"))
values.put("name", "");
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
long rowId = db.insert("test", null, values);
if (rowId < 0) {
throw new SQLException("Failed to insert row into " + url);
}
Uri newUrl = ContentUris.withAppendedId(CONTENT_URI, rowId);
getContext().getContentResolver().notifyChange(newUrl, null);
return newUrl;
}
@Override
public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
return true;
}
@Override
public Cursor query(Uri url, String[] projection, String where,
String[] whereArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
int match = sURLMatcher.match(url);
switch (match) {
case ALARMS:
qb.setTables("test");
break;
case ALARMS_ID:
qb.setTables("test");
qb.appendWhere("_id=");
qb.appendWhere(url.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Unknown URL " + url);
}
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
Cursor cur = qb.query(db, projection, where, whereArgs,null, null, sortOrder);
if (cur != null) {
cur.setNotificationUri(getContext().getContentResolver(), url);
}
return cur;
}
@Override
public int update(Uri url, ContentValues values, String where,String[] whereArgs) {
int count;
long rowId = 0;
int match = sURLMatcher.match(url);
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
switch (match) {
case ALARMS_ID: {
String segment = url.getPathSegments().get(1);
rowId = Long.parseLong(segment);
count = db.update("test", values, "_id=" + rowId, null);
break;
}
default: {
throw new UnsupportedOperationException(
"Cannot update URL: " + url);
}
}
getContext().getContentResolver().notifyChange(url, null);
return count;
}
}
转载自:http://dev.10086.cn/cmdn/bbs/viewthread.php?tid=37427&extra=page%3D1%26amp%3Bfilter%3Dtype%26amp%3Btypeid%3D67