`

Android数据库内容变化的监听

阅读更多

Android数据库内容变化的监听  

 

首先介绍内容监测的基本模式
基于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"只是说如果notifyChangeuriregisterContentObserver中的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的主要方法
Public Methods
void onChanged()
This method is called when the entire data set has changed, most likely through a call to requery() on a Cursor.
void onInvalidated()
This method is called when the entire data becomes invalid, most likely through a call to deactivate() or close() on a Cursor.
那么CursorAdapter是如何实现对基于uri的数据库内容变化进行监听呢?
它当然是借助Cursor来实现的。
但是CursorAdapterContentObserver相对应对外提供(可以重载)的接口是:
onContentChanged()
当时CursorAdapterDataSetObserver相对应对外提供(可以重载)的接口是:
onChanged()->notifyDataSetChanged()//这个消息并完全不是从Cursor传递来,它会在CursorAdapter内手动被调用
onInvalidated()->notifyDataSetInvalidated()//这个消息并不是从Cursor传递来。
具体可以参照
附件2的android.widget.CursorAdapter源代码
CursorAdapternotifyDataSetChanged()notifyDataSetInvalidated()事件可以继续往外传递
BaseAdapter为此提供了以下系列方法。
void notifyDataSetChanged()
Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.
void notifyDataSetInvalidated()
Notifies the attached observers that the underlying data is no longer valid or available.
void registerDataSetObserver(DataSetObserver observer)
Register an observer that is called when changes happen to the data used by this adapter.
void unregisterDataSetObserver(DataSetObserver observer)
Unregister an observer that has previously been registered with this adapter via registerDataSetObserver(DataSetObserver).
android.widget.BaseAdapter的部分源代码如下:
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { 
private final DataSetObservable mDataSetObservable = new DataSetObservable(); 
public boolean hasStableIds() { return false; } 
public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); } 
public void unregisterDataSetObserver(DataSetObserver observer) { mDataSetObservable.unregisterObserver(observer); } 
/** * Notifies the attached View that the underlying data has been changed * and it should refresh itself. */ 
public void notifyDataSetChanged() { mDataSetObservable.notifyChanged(); } 
public void notifyDataSetInvalidated() { mDataSetObservable.notifyInvalidated(); } 
-------------------省略------------------
注意:对于BaseAdapter,外部可以强行调用notifyDataSetChangednotifyDataSetInvalidated来通知DataSetObserver observer

 

转:

http://hubingforever.blog.163.com/blog/static/1710405792010101541326636/

 

分享到:
评论

相关推荐

    android 监听短信数据库

    在android当中动态的监听知信数据库是否有变化

    自定义ContentObserver监听数据库数据变化

    自定义ContentObserver监听数据库数据变化,在Observer里面的onChange实现回调,这里可以获取到最新变化的那条数据,代码亲测可行

    Android 使用ContentObserver监听数据库内容是否更改

    主要介绍了Android 使用ContentObserver监听数据库内容是否更改的相关资料,ContentObserver内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,需要的朋友可以参考下

    Android编程之监听器用法实例分析

    这里通过监听内容提供者数据变化和监听发送短信进行讲解监听器。如果用户提供者数据发生了变化,监听器立刻就能收到对数据库操作的记录,而监听器是采用通知的机制,如果不采用通知的机制也可以做,那就是不断的查询...

    Android App内监听截图加二维码功能代码

    Android系统有一个媒体数据库,每拍一张照片,或使用系统截屏截取一张图片,都会把这张图片的详细信息加入到这个媒体数据库,并发出内容改变通知,我们可以利用内容观察者(ContentObserver)监听媒体数据库的变化,...

    Android利用CursorLoader实现短信验证码自动填写

    所以,现在一般会选用监听数据库内容变化的方式来实现短信验证码自动填写。 网上对于利用监听数据库内容变化来实现短信验证码自动填写的文章也很多,主要分为一下步骤: 1. 继承ContentObserver实现一个短信数据库...

    Android最新资料以及源码

    内容索引:Java源码,Android,Android,文件管理  Android平台下的手机系统管理软件,就像电脑系统一样包括进程管理、文件管理和系统管理,具体来说,包括:  1、系统信息,查看设备系统版本,运营商及其系统信息. ...

    Android权限大全

    1、android.permission.ACCESS_CHECKIN_PROPERTIES : Allows read/write access to the “properties” table in the checkin database, to change values that get uploaded. 允许以read/write访问检入数据库...

    黎活明android教程的全程PPT

    数据库版本变化 D.编写代码完成添删改查操作(两种实现方法) E.事务的实现 F.采用ListView实现数据列表显示 2> 采用ContentProvider对外共享数据 第四天 1> 往通信录添加联系人,和获取联系人 2> 网络--获取...

    Android APP与媒体存储服务的交互

    Android 中,开发者的 APP 如何使用媒体存储服务(包含MediaScanner、MediaProvider以及媒体信息解析等部分),包括如何把 APP 新增或修改的文件更新到媒体数据库、如何在多媒体应用中隐藏 APP 产生的文件、如何监听...

    基于Java(Android)实现手机安全管家App【100011253】

    系统设计包括木马查杀,流量监控,通过iptable配置过滤规则,短信电话拦截,提升在5.0以上的系统,利用内容提供者监听系统短信数据库的变化和本地数据库的变化判断是否在黑名单中。进程管理,管理后天运行进程,垃圾...

    8天快速掌握Android系列视频之04_开发与 运行(卸载)第一个ANDROID应用

    ListView实现数据列表显示,20_采用ContentProvider对外共享数据,21_监听ContentProvider中数据的变化,22_访问通 信录中的联系人和添加联系人,23_网络通信之网络图片查看器,24_网络通信之网页源码查看器,25_...

    精通ANDROID 3(中文版)1/2

    7.4.7 使用菜单响应数据变化  7.5 通过XML文件加载菜单  7.5.1 XML菜单资源文件的结构  7.5.2 填充XML菜单资源文件  7.5.3 响应基于XML的菜单项  7.5.4 其他XML菜单标记简介  7.6 资源  7.7 小结  ...

    Android平台下传感器技术开发计步器应用

    结合实际案例, 介绍了在程序中注册传感器监听器对手机的加速度变化进行感应的方法,以及使用Intent 在Activity 与Service 之间进行通信, 以及对Android 平台下的嵌入式数据库SQLite进行操作的技巧,完成计步功能~

    Android实现短信验证码自动填写

    使用ContentProvider来监听短信数据库的变化,在自定义的ContentObserver当中实现onChange的方法进行监听特定手机号的短信,然后进行信息截取在填充到需要填充的位置。  ContentObserver即为内容监听者,当我们发送...

    Android 传感器应用举例

    Android 传感器应用举例 结合实际案例, 介绍了在程序中注册传感器监听器对手机的加速度变化进行...以及使用Intent 在Activity 与Service 之间进行通信, 以及对Android 平台下的嵌入式数据库SQLite 进行操作的技巧。

    传智播客Android视频教程-课程源码.rar

    数据库版本变化 D.编写代码完成添删改查操作(两种实现方法) E.事务的实现 F.采用ListView实现数据列表显示 2> 采用ContentProvider对外共享数据 第四天 1> 往通信录添加联系人,和获取联系人 2> 网络--获取数据...

    黑马程序员 安卓学院 万元哥项目经理 分享220个代码实例

    |--监听之EditText内容变化监听 |--监听之GridView条目点击监听 |--监听之ListView条目点击事件监听 |--监听之ListView滑动监听 |--监听之单击监听的两种定义 |--监听之双击监听 |--监听之电话状态监听 |--监听之...

    8天快速掌握Android系列视频之07_查看应用输出的错误信息 与如何部署应用到真实手机

    ListView实现数据列表显示,20_采用ContentProvider对外共享数据,21_监听ContentProvider中数据的变化,22_访问通 信录中的联系人和添加联系人,23_网络通信之网络图片查看器,24_网络通信之网页源码查看器,25_...

Global site tag (gtag.js) - Google Analytics