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 ...
随机推荐
- 【转】javascript 执行环境,变量对象,作用域链
这篇文章比较清晰的解释了一些作用域链相关的概念,忍不住收藏了 原文地址:http://segmentfault.com/a/1190000000533094 前言 这几天在看<javascrip ...
- Django 学习之---缓存系统
一.浏览器缓存机制 Cache-control策略(重点关注) Cache-Control与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务 ...
- springboot mvc beetl模板 自定义错误的后缀问题
@Component public class BeetlErrorViewResolver implements ErrorViewResolver { private static final M ...
- Linux实战教学笔记28:企业级LNMP环境应用实践
一,LNMP应用环境 1.1 LNMP介绍 大约在2010年以前,互联网公司最常用的经典Web服务环境组合就是LAMP(即Linux,Apache,MySQL,PHP),近几年随着Nginx Web服 ...
- 【LA11248 训练指南】网络扩容【最大流】
题意: 给定一个有向网络,每条边均有一个容量.问是否存在一个从点1到点N,流量为C的流.如果不存在,是否可以恰好修改一条弧的容量,使得存在这样的流? 分析: 先跑一遍最大流,如果最大流大于等于C,则输 ...
- Ubuntu14.04下opencv卸载与重装
参考链接:http://askubuntu.com/questions/334158/installing-opencv http://stackoverflow.com/questions/1313 ...
- Tsung压力测试:Openfire
环境准备 安装Tsung.安装openfire.安装Spark 要对openfire进行压力测试,因此我们主要讲解如何利用jabber_register.xml在openfire上面注册用户,以及利用 ...
- Openssl enc命令
一.简介 enc - 对称加密例程,使用对称密钥对数据进行加解密,特点是速度快,能对大量数据进行处理.算法有流算法和分组加密算法,流算法是逐字节加,由于其容易被破译,现在已很少使用:分组加密算法是将数 ...
- 使用dataview组件显示服务器端xml文件数据
来自<sencha touch权威指南>,约193页开始 ------------------------------------- (1)app.js代码: Ext.require([' ...
- CENTOS7 YUM安装BOOST1.53(静态版本)
按照之前的博文更新163的源之后,执行: yum install boost-static.i686 yum install boost-devel.i686 yum install boost-do ...