Android-Observer(内容观察者)
内容提供者应用暴露的数据,是被多个其他应用访问(insert,update,delete,query),但如果L应用要查询(内容提供者应用暴露的数据),难道要开启子线程一直循环去查询 ?
答:开启子线程一直循环去查询是不合理的(是严重的错误),所以Android提供了Observer(内容观察者)这种机制,当内容提供者里面的数据发送变化(insert, update, delete),就会发出通知,L应用监听到发出的通知,就去查询数据,这样就完美解决了这个问题。
以下这幅图:把 (监听uri数据的变化:内容观察者ContentObserver)写到了L应用里面,其实是L应用调用ContentResolver.监听uri数据的变化:内容观察者ContentObserver

S应用--> MyContentProvider 增删改查 代码
只有 insert,update, delete,能够证明数据发送了改变,所以通过getContext().getContentResolver().notifyChange(uri, null);发出改变通知
private MySqliteOpenHeper mySqliteOpenHeper;
    /**
     * 只要在AndroidManifest.xml中配置了provider组件
     * 应用打开后,会自动启动此方法
     * @return
     */
    @Override
    public boolean onCreate() {
        Log.d(TAG, "onCreate()");
        mySqliteOpenHeper = MySqliteOpenHeper.getInstance(getContext());
        return false;
    }
    /**
     * 查询
     * @return
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        SQLiteDatabase db = mySqliteOpenHeper.getReadableDatabase();
        // 查询全部
        Cursor cursor = db.query("cat", // 表名
                projection, // 查询的列
                null,   // selection 查询的条件 xxx=?
                null, // selectionArgs 查询条件的值
                null, // groupBy 分组
                null, // having 分组过滤条件
                "_id desc"); // orderBy 排序 --> 倒序
        // 在内容提供者里面,千万不能关闭数据库,关闭游标
        return cursor;
    }
    /**
     * 增加
     * @return
     */
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        SQLiteDatabase database = mySqliteOpenHeper.getWritableDatabase();
        long resultID = database.insert("cat", null, values);
        // 在内容提供者里面,千万不能关闭数据库,关闭游标
        /**
         * 证明数据发送了改变,所以需要通知其他应用
         * 内容观察者机制: -->发出改变通知给---> 其他应用(内容观察者监听器,监听到发送的改变通知,然后进行查询)
         */
        getContext().getContentResolver().notifyChange(uri, null);
        return uri;
    }
    /**
     * 修改
     * @return
     */
    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        SQLiteDatabase database = mySqliteOpenHeper.getWritableDatabase();
        // 参数一:表名   参数二:其他应用传递过来的ContentValues   参数三:其他应用传递过来的查询条件
        int updateResult = database.update("cat", values, selection, selectionArgs);
        // 在内容提供者里面,千万不能关闭数据库,关闭游标
        /**
         * 证明数据发送了改变,所以需要通知其他应用
         * 内容观察者机制: -->发出改变通知给---> 其他应用(内容观察者监听器,监听到发送的改变通知,然后进行查询)
         */
        getContext().getContentResolver().notifyChange(uri, null);
        return updateResult;
    }
    /**
     * 删除
     * @return
     */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        SQLiteDatabase database = mySqliteOpenHeper.getWritableDatabase();
        int deleteResult = database.delete("cat", selection, selectionArgs);
        // 在内容提供者里面,千万不能关闭数据库,关闭游标
        /**
         * 证明数据发送了改变,所以需要通知其他应用
         * 内容观察者机制: -->发出改变通知给---> 其他应用(内容观察者监听器,监听到发送的改变通知,然后进行查询)
         */
        getContext().getContentResolver().notifyChange(uri, null);
        return deleteResult;
    }
S应用--> AndroidManifest.xml 对外暴露:
<!--
MyContentProviderNew是组件需要配置
可以把MyContentProviderNew看作是服务器
authorities 看作是服务器 服务器有访问的链接,authorities(授权) ,是唯一标识
android:enabled="true" 可以被系统实例化
android:exported="true" 允许对外输出
-->
<provider
android:authorities="autho.prov.cp.MyContentProviderNew"
android:name=".cp.MyContentProviderNew"
android:enabled="true"
android:exported="true"
/>
L应用 --> NewMainActivity监听发出的改变通知
package liudeli.cp.client; import android.app.Activity;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler; public class NewMainActivity extends Activity { /**
* 定义ContentResolver
*/
private ContentResolver contentResolver; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // S应用对外暴露的授权标识
Uri uri = Uri.parse("content://autho.prov.cp.MyContentProviderNew"); contentResolver = getContentResolver(); /**
* 注册 内容观察者:监听S应用发出的改变通知
* 参数一:S应用提供的授权
* 参数二:意思是 是否监 和它表有关系的表 (例如:.../dog .../dog/#)
* 参数三:监听器
*
* 注册监听: 需要:contentResolver.
*/
contentResolver.registerContentObserver(uri, true, contentObserver);
} /**
* 监听器:用来监听S应用发出的改变通知
*/
private ContentObserver contentObserver = new ContentObserver(new Handler()) { @Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
/**
* 通过contentProvider.query(......) 进行查询S应用数据
*/
} @Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
/**
* 通过contentProvider.query(......) 进行查询S应用数据
*/
}
}; @Override
protected void onDestroy() {
super.onDestroy();
/**
* 解除:内容观察者:监听
* 解除也需要:contentResolver.
*/
contentResolver.unregisterContentObserver(contentObserver);
}
}
可以把 内容观察者ContentObserver理解为:广播, 只是代码和广播不一样而已

Android-Observer(内容观察者)的更多相关文章
- Android中内容观察者的使用---- ContentObserver类详解 (转)
		
前言: 工作中,需要开启一个线程大量的查询某个数据库值发送了变化,导致的开销很大,后来在老大的指点下,利用了 ContentObserver完美的解决了该问题,感到很兴奋,做完之后自己也对Conten ...
 - Android 利用内容观察者实现短信窃听
		
<Android 内容观察者的原理>中介绍了内容观察者的一些基本原理,并做了简单的实战,本文接着进一步做一个小项目实战 package com.wuyudong.smslistener; ...
 - 无废话Android之内容观察者ContentObserver、获取和保存系统的联系人信息、网络图片查看器、网络html查看器、使用异步框架Android-Async-Http(4)
		
1.内容观察者ContentObserver 如果ContentProvider的访问者需要知道ContentProvider中的数据发生了变化,可以在ContentProvider 发生数据变化时调 ...
 - android ContentObserver内容观察者基本使用
		
package com.example.observertest; import android.content.ContentResolver; import android.database.Co ...
 - Android -- ContentObserver 内容观察者
		
1. 实现原理图 2. 示例代码 (暂时有个问题,短信观察者 收到一条短信时 onchange方法会执行两次, 解决方法为:每次监听到变化的时候就去取最新短信的id,跟上次取的比较,如果一样的就不做处 ...
 - Android中内容观察者的使用---- ContentObserver类详解
		
详解:http://blog.csdn.net/qinjuning/article/details/7047607
 - Android 内容观察者的原理
		
拦截短信,比如当发短信的时候,就把短信读取出来,当系统的短信发生变化的时候,大叫一声,把数据发送到公共的消息邮箱里面,我们的应用通过内容观察者观察公共的消息邮箱 获取ContentResolver对象 ...
 - Android开发之内容观察者
		
内容观察者: 当关注应用的数据库数据改变时,内容提供者会发出通知,在内容提供者的uri上注册一个内容观察者,就可以收到数据改变的通知 实现步骤: 1.假如是自定义的ContentProvider,需要 ...
 - Android(java)学习笔记253:ContentProvider使用之内容观察者02
		
下面通过3个应用程序之间的交互说明一下内容观察者: 一. 如下3个应用程序为相互交互的: 二.交互逻辑图: 三.具体代码: 1. 16_数据库工程: (1)数据库帮助类BankDBOpenHelp ...
 
随机推荐
- 04_java之基本语法02
			
01switch语句解构 * A:switch语句解构 a:switch只能针对某个表达式的值作出判断,从而决定程序执行哪一段代码. b:格式如下: swtich(表达式){ case 常量1 : 要 ...
 - TCP报文大小
			
链路层(二层)MTU最大传输单元:1500KByte.每个以太网帧64bytes-1518bytes,减去帧头(DMAC目的MAC地址48bit=6Bytes+SMAC源MAC地址48bit=6Byt ...
 - mybatis 传入集合参数遍历 查询总结
			
出自:http://blog.csdn.net/u013628152/article/details/51184641 1. findByIds(List ids) 如果参数的类型是List, 则在使 ...
 - mysql 挑选列导入
			
insert into boleht_development.`htprojects`(id,pname,`general`,imgsrc,whatwedo,howwedo,bp) select ci ...
 - KVM镜像image 转换 调整
			
qemu-img create -f raw test.raw 8G 创建一个raw格式,大小为8G的镜像. qemu-img info disk1.qcow2 #查看镜像大小及实际占用多少空 ...
 - 配置python的豆瓣source
			
sunny@sunny-ThinkPad-T450:~$ mkdir ~/.pip sunny@sunny-ThinkPad-T450:~$ gedit ~/.pip/pip.conf [global ...
 - MonoDevelop Assembly Browser
			
[MonoDevelop Assembly Browser] View -> Assembly Browser,通过此窗口可以查看Dll的反编译后的代码. 还有几款免费的替代产品可以使用, 虽然 ...
 - hdu3999-The order of a Tree                                             (二叉树的先序遍历)
			
http://acm.hdu.edu.cn/showproblem.php?pid=3999 The order of a Tree Time Limit: 2000/1000 MS (Java/Ot ...
 - 利用Fiddler对Android模拟器网络请求进行抓包
			
安装使用Fiddler 下载安装Fiddler的方法这里就略过了,一路Next就行了.装好之后运行软件,正常情况这个时候我们已经可以对电脑的网络请求进行抓包了.Fiddler默认的代理地址是127.0 ...
 - SpringBoot 集成Mybatis时  使用通用插件Mapper 注意事项
			
1.如果在SpringBoot的启动入口类上面加入注解 @MapperScan(basePackages = "com.leecx.mapper") 使用的是 org ...