在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的文字自动变化设置到数据库中的字符串。[code]03 | import android.app.Activity; |
04 | import android.content.Intent; |
05 | import android.database.ContentObserver; |
06 | import android.os.Bundle; |
07 | import android.os.Handler; |
08 | import android.view.View; |
09 | import android.widget.Button; |
11 | public class ListenDataTest extends Activity{ |
12 | private Button testBtn; |
15 | protected void onCreate(Bundle savedInstanceState) { |
16 | super .onCreate(savedInstanceState); |
17 | setContentView(R.layout.listen_data_test); |
18 | getContentResolver().registerContentObserver(DataChangeProvider.CONTENT_URI, |
21 | testBtn = (Button)findViewById(R.id.test_btn); |
22 | testBtn.setOnClickListener( new View.OnClickListener() { |
24 | public void onClick(View v) { |
25 | Intent in = new Intent(ListenDataTest. this ,DataChangeTest. class ); |
33 | private ContentObserver cob = new ContentObserver( new Handler()) { |
36 | public boolean deliverSelfNotifications() { |
37 | return super .deliverSelfNotifications(); |
41 | public void onChange( boolean selfChange) { |
42 | super .onChange(selfChange); |
43 | testBtn.setText(DataUtils.getChangeName(getApplicationContext())); |
49 | protected void onDestroy() { |
51 | getContentResolver().unregisterContentObserver(cob); |
[code]03 | import android.app.Activity; |
04 | import android.content.ContentValues; |
05 | import android.content.Intent; |
06 | import android.database.ContentObservable; |
07 | import android.database.ContentObserver; |
08 | import android.os.Bundle; |
09 | import android.os.Handler; |
10 | import android.view.View; |
11 | import android.widget.Button; |
13 | public class DataChangeTest extends Activity{ |
14 | private Button dataBtn; |
15 | DataSqlite mDataSqlite; |
17 | protected void onCreate(Bundle savedInstanceState) { |
18 | super .onCreate(savedInstanceState); |
19 | setContentView(R.layout.data_change_test); |
20 | dataBtn = (Button)findViewById(R.id.data_test_btn); |
21 | mDataSqlite = new DataSqlite( this ); |
22 | dataBtn.setOnClickListener( new View.OnClickListener() { |
24 | public void onClick(View v) { |
25 | ContentValues con = new ContentValues(); |
26 | con.put( "name" , "数据变化了" ); |
27 | getContentResolver().insert(DataChangeProvider.CONTENT_URI, con); |
[code]004 | import android.content.ContentProvider; |
005 | import android.content.ContentUris; |
006 | import android.content.ContentValues; |
007 | import android.content.Context; |
008 | import android.content.UriMatcher; |
009 | import android.database.Cursor; |
010 | import android.database.SQLException; |
011 | import android.database.sqlite.SQLiteDatabase; |
012 | import android.database.sqlite.SQLiteOpenHelper; |
013 | import android.database.sqlite.SQLiteQueryBuilder; |
014 | import android.database.sqlite.SQLiteDatabase.CursorFactory; |
015 | import android.net.Uri; |
016 | import android.text.TextUtils; |
018 | public class DataChangeProvider extends ContentProvider{ |
019 | private SQLiteOpenHelper mOpenHelper; |
020 | private static final int ALARMS = 1 ; |
021 | private static final int ALARMS_ID = 2 ; |
022 | private static final UriMatcher sURLMatcher = new UriMatcher(UriMatcher.NO_MATCH); |
026 | sURLMatcher.addURI( "ty.com.lto" , "test" , ALARMS); |
027 | sURLMatcher.addURI( "ty.com.lto" , "test/#" , ALARMS_ID); |
030 | private static class DatabaseHelper extends SQLiteOpenHelper{ |
031 | private static final String TEST_DATABASE = "test.db" ; |
032 | private static final int VERSION = 1 ; |
034 | public DatabaseHelper(Context context) { |
035 | super (context, TEST_DATABASE, null , VERSION); |
041 | public void onCreate(SQLiteDatabase db) { |
042 | String sql = "CREATE TABLE " + "test" + " (" + |
043 | "_id INTEGER PRIMARY KEY," + |
050 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
051 | String sql = "DROP TABLE IF EXIST " +TEST_DATABASE; |
058 | public DataChangeProvider() { |
062 | public int delete(Uri url, String where, String[] whereArgs) { |
063 | SQLiteDatabase db = mOpenHelper.getWritableDatabase(); |
066 | switch (sURLMatcher.match(url)) { |
068 | count = db.delete( "test" , where, whereArgs); |
071 | String segment = url.getPathSegments().get( 1 ); |
072 | rowId = Long.parseLong(segment); |
073 | if (TextUtils.isEmpty(where)) { |
074 | where = "_id=" + segment; |
076 | where = "_id=" + segment + " AND (" + where + ")" ; |
078 | count = db.delete( "test" , where, whereArgs); |
081 | throw new IllegalArgumentException( "Cannot delete from URL: " + url); |
084 | getContext().getContentResolver().notifyChange(url, null ); |
089 | public String getType(Uri url) { |
090 | int match = sURLMatcher.match(url); |
093 | return "vnd.android.cursor.dir/alarms" ; |
095 | return "vnd.android.cursor.item/alarms" ; |
097 | throw new IllegalArgumentException( "Unknown URL" ); |
102 | public Uri insert(Uri url, ContentValues initialValues) { |
103 | if (sURLMatcher.match(url) != ALARMS) { |
104 | throw new IllegalArgumentException( "Cannot insert into URL: " + url); |
107 | ContentValues values; |
108 | if (initialValues != null ) { |
109 | values = new ContentValues(initialValues); |
111 | values = new ContentValues(); |
114 | if (!values.containsKey( "name" )) |
115 | values.put( "name" , "" ); |
117 | SQLiteDatabase db = mOpenHelper.getWritableDatabase(); |
118 | long rowId = db.insert( "test" , null , values); |
120 | throw new SQLException( "Failed to insert row into " + url); |
122 | Uri newUrl = ContentUris.withAppendedId(CONTENT_URI, rowId); |
123 | getContext().getContentResolver().notifyChange(newUrl, null ); |
128 | public boolean onCreate() { |
129 | mOpenHelper = new DatabaseHelper(getContext()); |
134 | public Cursor query(Uri url, String[] projection, String where, |
135 | String[] whereArgs, String sortOrder) { |
136 | SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); |
137 | int match = sURLMatcher.match(url); |
140 | qb.setTables( "test" ); |
143 | qb.setTables( "test" ); |
144 | qb.appendWhere( "_id=" ); |
145 | qb.appendWhere(url.getPathSegments().get( 1 )); |
148 | throw new IllegalArgumentException( "Unknown URL " + url); |
151 | SQLiteDatabase db = mOpenHelper.getReadableDatabase(); |
152 | Cursor cur = qb.query(db, projection, where, whereArgs, null , null , sortOrder); |
154 | cur.setNotificationUri(getContext().getContentResolver(), url); |
161 | public int update(Uri url, ContentValues values, String where,String[] whereArgs) { |
164 | int match = sURLMatcher.match(url); |
165 | SQLiteDatabase db = mOpenHelper.getWritableDatabase(); |
168 | String segment = url.getPathSegments().get( 1 ); |
169 | rowId = Long.parseLong(segment); |
170 | count = db.update( "test" , values, "_id=" + rowId, null ); |
174 | throw new UnsupportedOperationException( |
175 | "Cannot update URL: " + url); |
178 | getContext().getContentResolver().notifyChange(url, null ); |
[code]01 | <?xml version= "1.0" encoding= "utf-8" ?> |
04 | android:versionCode= "1" |
05 | android:versionName= "1.0" |
07 | <application android:icon= "@drawable/icon" android:label= "@string/app_name" > |
08 | <provider android:name= "DataChangeProvider" android:authorities= "ty.com.lto" /> |
09 | <activity android:name= ".ListenDataTest" |
10 | android:label= "@string/app_name" > |
12 | <action android:name= "android.intent.action.MAIN" /> |
13 | <category android:name= "android.intent.category.LAUNCHER" /> |
16 | <activity android:name= ".DataChangeTest" android:label= "@string/app_name" /> |
18 | <uses-permission android:name= "android.permission.INTERNET" /> |
19 | <uses-permission android:name= "android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> |
|