问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

android 数据库怎么监听数据变化

发布网友 发布时间:2022-04-07 18:21

我来回答

5个回答

懂视网 时间:2022-04-07 22:43

package com.example.sqlitetransaction; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.database.sqlite.SQLiteDatabase.CursorFactory; 6 import android.database.sqlite.SQLiteOpenHelper; 7 import android.util.Log; 8 9 public class MydbOpenHelper extends SQLiteOpenHelper { 10 11 // 12 public MydbOpenHelper(Context context, String name, CursorFactory factory, 13 int version) { 14 super(context, name, factory, version); 15 // TODO Auto-generated constructor stub 16 } 17 18 19 //oncreate函数当数据库第一次被创建的时候会调用 20 @Override 21 public void onCreate(SQLiteDatabase db) { 22 // TODO Auto-generated method stub 23 String createtable = "create table user(id int, name varchar(20), money int);"; 24 db.execSQL(createtable); 25 System.out.println("MydbOpenHelper.onCreate()"); 26 } 27 28 29 //onUpgrade当你的数据库版本升级的时候会调用 30 @Override 31 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 32 // TODO Auto-generated method stub 33 //更改数据库的表结构 34 // user(id,name,password) user(id,name,password,gender) 35 // 36 // db.execSQL(""); 37 Log.i("MydbOpenHelper", "oldervserion"+oldVersion+"newversion"+newVersion); 38 System.out.println("MydbOpenHelper.onUpgrade()"); 39 40 } 41 42 } MydbOpenHelper.java

 

技术分享
 1 package com.example.sqlitetransaction;
 2 
 3 import android.app.Activity;
 4 import android.content.ContentValues;
 5 import android.database.Cursor;
 6 import android.database.sqlite.SQLiteDatabase;
 7 import android.os.Bundle;
 8 import android.util.Log;
 9 import android.view.Menu;
10 import android.view.MenuItem;
11 
12 public class MainActivity extends Activity {
13  SQLiteDatabase db;
14 
15  @Override
16 protected void onCreate(Bundle savedInstanceState) {
17  super.onCreate(savedInstanceState);
18  setContentView(R.layout.activity_main);
19  
20  MydbOpenHelper helper = new MydbOpenHelper(this, "count.db", null,1);
21  db = helper.getReadableDatabase();
22  
23  //insert();
24  try {
25   update(); 
26   query();
27  } 
28  finally{
29   db.close();  
30  }
31  
32  }
33 private void update(){
34  db.beginTransaction();
35  try{
36  ContentValues cv = new ContentValues();
37  cv.put("money", 7000);
38  db.update("user", cv, "id=1", null);
39  
40  //int b = 1/0;
41  
42   cv.clear();
43  cv.put("money", 11000);
44  db.update("user", cv, "id=2", null);
45   db.setTransactionSuccessful();
46  }catch(Exception e){
47  
48  }finally{
49   db.endTransaction();
50  }
51 
52  }
53 private void query(){
54  Cursor c = db.rawQuery("select * from user", null);
55  
56  while(c.moveToNext()){
57  int id = c.getInt(c.getColumnIndex("id"));
58  String username = c.getString(c.getColumnIndex("name"));
59  String money = c.getString(c.getColumnIndex("money"));
60  Log.i("sqlitetransaction", id+","+username+","+money);
61  }
62  }
63 private void insert(){
64  ContentValues cv = new ContentValues();
65  cv.put("id", 1);
66  cv.put("name", "user1");
67  cv.put("money", 8000);
68  db.insert("user", null, cv);
69  cv.clear();
70  
71  cv.put("id", 2);
72  cv.put("name", "user2");
73  cv.put("money", 10000);
74  db.insert("user", null, cv);
75  cv.clear();
76  }
77 }
MainActivity.java

 

007_01SQLiteTransaction

标签:

热心网友 时间:2022-04-07 19:51

在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 ),在这个方法里去操作数据库的使用,针对变化后的使用。

热心网友 时间:2022-04-07 21:09

可以使用ContentObserver对象监听,如下:
public final void registerContentObserver(Uri uri, boolean notifyForDescendents, ContentObserver observer)
功能:为指定的Uri注册一个ContentObserver派生类实例,当给定的Uri发生改变时,回调该实例对象去处理。
参数:uri 需要观察的Uri(需要在UriMatcher里注册,否则该Uri也没有意义了)
notifyForDescendents 为false 表示精确匹配,即只匹配该Uri
为true 表示可以同时匹配其派生的Uri,举例如下:
假设UriMatcher 里注册的Uri共有一下类型:
1 、content://com.qin.cb/student (学生)
2 、content://com.qin.cb/student/#
3、 content://com.qin.cb/student/schoolchild(小学生,派生的Uri)
假设我们当前需要观察的Uri为content://com.qin.cb/student,如果发生数据变化的 Uri 为
content://com.qin.cb/student/schoolchild ,当notifyForDescendents为 false,那么该ContentObserver会监听不到,
但是当notifyForDescendents 为ture,能捕捉该Uri的数据库变化。

热心网友 时间:2022-04-07 22:43

首先介绍内容监测的基本模式
基于uri的内容监测的基本模式被android.content.ContentResolver实现。
它为基于Uri的内容监测的提供了一个平台。(其实如果有必要,我们可以自己实现一个)
ContentResolver为此提供了三个方法:
注册*到某个uri
public final void registerContentObserver (Uri uri, boolean notifyForDescendents, ContentObserver observer)
Register an observer class that gets callbacks when data identified by a given content URI changes.
Parameters
uri The URI to watch for changes. This can be a specific row URI, or a base URI for a whole class of content.
notifyForDescendents If true changes to URIs beginning with uri will also cause notifications to be sent.
If false only changes to the exact URI specified by uri will cause notifications to be sent.
If true, than any URI values at or below the specified URI will also trigger a match.
observer The object that receives callbacks when changes occur.
取消被注册的*
public final void unregisterContentObserver (ContentObserver observer)
Unregisters a change observer.
参数
observer The previously registered observer that is no longer needed.
通知所有注册到uri的*,告诉他们内容发生了改变。
public void notifyChange (Uri uri, ContentObserver observer)
Notify registered observers that a row was updated. To register, call registerContentObserver(). By default, CursorAdapter objects will get this notification.
参数
observer The observer that originated the change, may be null .用以说明observer是第一个发现内容改变的ContentObserver,可为null.
通知所有注册到uri的*,告诉他们内容发生了改变。
public void notifyChange (Uri uri, ContentObserver observer, boolean syncToNetwork)
Notify registered observers that a row was updated. To register, call registerContentObserver(). By default, CursorAdapter objects will get this notification.
参数
observer The observer that originated the change, may be null 用以说明observer是第一个发现内容改变的ContentObserver,可为null
syncToNetwork If true, attempt to sync the change to the network.
注1:"基于uri的内容监测的基本模式被android.content.ContentResolver实现",严格来说ContentResolver至少提供了接口。
真正的实现在android.content.ContentService.
其实ContentResolver为基于Uri的内容监测所提供的方法只是调用ContentService相关的方法
注2:"注册*到uri"只是说如果notifyChange的uri和registerContentObserver中的uri相匹配,则调用observer的方法onChange。
内容*ContentObserver主要有三个方法
public boolean deliverSelfNotifications ()
Returns true if this observer is interested in notifications for changes made through the cursor the observer is registered with.
注:这个函数的使用还是puzzle.
public final void dispatchChange (boolean selfChange)
注:这个是为提供用handler执行onChange的一个接口。所以一般比没必要重载它。
public void onChange (boolean selfChange)
This method is called when a change occurs to the cursor that is being observed.
参数
selfChange true if the update was caused by a call to commit on the cursor that is being observed.
注1:这个就是我们需要重载的函数,在里面可以实现对内容改变的个性化响应。
关于ContentObserver的更多内容请参阅《内容*ContentObserver》。
基本使用是这样的:
首先使用registerContentObserver注册observer*到uri,然后在内容发生改变时,就调用notifyChange通知系统所有注册到该uri的*,告诉他们内容发生了改变。
这时相应的*的dispatchChange方法被调用,在dispatchChange中onChange被调用。
最后如果不想让observer*uri相关的内容监听,可以调用unregisterContentObserver来取消注册。

对数据库改变的监测是如何实现的呢?
在providers对数据进行改变后,会通过getContext().getContentResolver().notifyChange的发生相应的uri的内容发生了改变
比如:com.android.providers.contacts中的ContactsProvider2
ContactsProvider2.java文件
public class ContactsProvider2 extends SQLiteContentProvider implements OnAccountsUpdateListener {
-------------------省略------------------
@Override
public Uri insert(Uri uri, ContentValues values) {
waitForAccess();
return super.insert(uri, values);
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-------------------省略------------------
waitForAccess();
return super.update(uri, values, selection, selectionArgs);
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
waitForAccess();
return super.delete(uri, selection, selectionArgs);
}
}
-------------------省略------------------
protected void notifyChange() {
notifyChange(mSyncToNetwork);
mSyncToNetwork = false;
}

protected void notifyChange(boolean syncToNetwork) {
getContext().getContentResolver().notifyChange(ContactsContract.AUTHORITY_URI, null,
syncToNetwork);
}
-------------------省略------------------
}
SQLiteContentProvider.java文件
public abstract class SQLiteContentProvider extends ContentProvider
implements SQLiteTransactionListener {
@Override
public Uri insert(Uri uri, ContentValues values) {
Uri result = null;
boolean applyingBatch = applyingBatch();
if (!applyingBatch) {
mDb = mOpenHelper.getWritableDatabase();
mDb.beginTransactionWithListener(this);
try {
result = insertInTransaction(uri, values);
if (result != null) {
mNotifyChange = true;
}
mDb.setTransactionSuccessful();
} finally {
mDb.endTransaction();
}

onEndTransaction();
} else {
result = insertInTransaction(uri, values);
if (result != null) {
mNotifyChange = true;
}
}
return result;
}
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-------------------省略------------------
}
public int delete(Uri uri, String selection, String[] selectionArgs) {
-------------------省略------------------
}
-------------------省略------------------
protected abstract void notifyChange();
-------------------省略------------------
protected void onEndTransaction() {
if (mNotifyChange) {
mNotifyChange = false;
notifyChange();
}
}
-------------------省略------------------
}
那么Cursor是如何实现对基于uri的数据库内容变化进行监听呢?
只要把一个*ContentObserver对uri使用ContentResolver的registerContentObserver方法进行注册。
如果相应uri的数据库内容变化发变化,先通知ContentObserver,再又让它通知Cursor。
当然为了方便系统把ContentObserver设计成了内部类。
具体可见在Cursor接口的一个实现android.database.AbstractCursor。
AbstractCursor.java文件请见附件1
同时Cursor为我们提供了setNotificationUri(ContentResolver cr, Uri notifyUri)让它内部类的ContentObserver注册到ContentResolver的某个Uri上.
具体代码参见附件1。
那么外部如何监听Cursor呢?。
Cursor为外部监测数据库的变化提供了以下接口:
abstract void registerContentObserver(ContentObserver observer)
Register an observer that is called when changes happen to the content backing this cursor.
注1:当数据库内容变化时通知observer,具体见附件1的onChange(boolean selfChange)函数.
注2:这个*observer主要是在setNotificationUri(ContentResolver cr, Uri notifyUri)中notifyUri对应的数据库内容发生变化时被通知的(间接),
abstract void unregisterContentObserver(ContentObserver observer)
Unregister an observer that has previously been registered with this cursor via registerContentObserver(ContentObserver).

另外,Cursor还为我们提供了接口,让外部可以通过注册一个DataSetObserver来对Cursor的requery(), deactivate(), close()行为进行监听。
abstract void registerDataSetObserver(DataSetObserver observer)
Register an observer that is called when changes happen to the contents of the this cursors data set, for example, when the data set is changed via requery(), deactivate(), or close().
注1:当Cursor发生requery(), deactivate(), or close()时通知DataSetObserver observer
abstract void unregisterDataSetObserver(DataSetObserver observer)
Unregister an observer that has previously been registered with this cursor via registerContentObserver(ContentObserver).
DataSetObserver的主要方法

热心网友 时间:2022-04-08 00:35

你在数据里写个*呗
增删查改都触发一下
自己写的程序怎么弄都可以啦
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
母亲55岁得了糖尿病,吃药控制在9以内,最近有点效果不好,到13点几了... ...很害怕发展成糖尿病足,有什么方法控制血糖吗? 我的妈妈得了糖尿病,那个什么值8点多,似乎不能治好,那么如果能控制血糖... 由糖尿病引起的白内障怎样才能控制?最好用中药的方法或者说按摩哪个穴位... 新凯美瑞2.5发动机和8自动变速箱是进口的吗? 网页图片下载神器!图片收集与管理利器Eagle ...怎么弄到自己的电脑里面去自己玩,不用4399游戏盒。 关于足部反射区,懂中医的入 脚部反射区图解图片 足部反射区疼痛怎么办 ai中怎么调整dpi,尺寸不变 丽江旅游必去的景点有哪些? ai里没有高dpi显示缩放 丽江有好玩的地方吗?在哪里玩,更有意思些? 丽江都有哪些景点 想和朋友们去丽江玩,想问哪都有什么美食美景呢?? 丽江在那里? 泸沽湖里格岛邮政编码 朋友你好,我想知道你用什么软件翻译的藏文,谢谢 有藏文翻译网站或软件麽 如何使用佳能相机的Wi 藏文,安卓手机下载那个软件,能翻译成汉语, 我心已死藏语翻译软件 清华同方笔记本电脑开机时系统启动然后即卡住开不开机怎么办 为什么清华同方的笔记本开机之后进不了系统 清华同方笔记本U盘装完系统重启后 显示windows未能启动? 清华同方电脑开机出现invalid partition table 进不了系统怎么办? 我的手机型号是华BLN_AL10支持无线充吗? 急。我的电脑是清华同方WIN7家庭版,昨天用还好好的,今天就进不去系统了,是为什么啊???? 型号:HUAWEI MLA-AL10的手机有无线充功能吗? Adobe Illustrator如何设定dpi 丽江旅游不得不去的好地方是?有相对好玩的吗? win10怎样设置ai的dpi 去丽江古城,玉龙雪山,蓝月谷,里格岛,草海,路线怎么安排最好 b站4连是什么意思 用ai图做了一半才想起来忘了设置dpi,该怎么看啊?还可以改吗 ai考试作业 ,他说格式要求1920*1080 分辨率350dpi怎么设置 用AI或者PS实现同一张纸上不同区域用不同dpi打印 看视频送三连我受影响吗 excel共享文档 不同颜色 应用于AI的照片,分辨率要改成300dpi吗? 为何excel2007的“共享工作簿”按钮是灰色的? 联通的5G网络制式是什么? 宏基4736G的键盘上面的键位怎么拆装 excel 2003 共享文档 工具-->保护-->允许用户编辑区域为灰色?为什么? 网络位置excel打开后,显示为只读模式,共享工作簿为灰色的,想取消只读模式,怎么办? Excel文件打不开,打开后菜单选项卡都是灰色的。但是正常的Excel程序是可以打开的。 你好,我的excel最近使用文档那里还是灰色的,不能修改,求助求助 宏基笔记本怎么把键盘拆下 共享excel表格,2010版2007版都能打开,突然2007不能打开了,打开全灰色,是什么原因?