内容提供者应用暴露的数据,是被多个其他应用访问(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(内容观察者)的更多相关文章

  1. Android中内容观察者的使用---- ContentObserver类详解 (转)

    前言: 工作中,需要开启一个线程大量的查询某个数据库值发送了变化,导致的开销很大,后来在老大的指点下,利用了 ContentObserver完美的解决了该问题,感到很兴奋,做完之后自己也对Conten ...

  2. Android 利用内容观察者实现短信窃听

    <Android 内容观察者的原理>中介绍了内容观察者的一些基本原理,并做了简单的实战,本文接着进一步做一个小项目实战 package com.wuyudong.smslistener; ...

  3. 无废话Android之内容观察者ContentObserver、获取和保存系统的联系人信息、网络图片查看器、网络html查看器、使用异步框架Android-Async-Http(4)

    1.内容观察者ContentObserver 如果ContentProvider的访问者需要知道ContentProvider中的数据发生了变化,可以在ContentProvider 发生数据变化时调 ...

  4. android ContentObserver内容观察者基本使用

    package com.example.observertest; import android.content.ContentResolver; import android.database.Co ...

  5. Android -- ContentObserver 内容观察者

    1. 实现原理图 2. 示例代码 (暂时有个问题,短信观察者 收到一条短信时 onchange方法会执行两次, 解决方法为:每次监听到变化的时候就去取最新短信的id,跟上次取的比较,如果一样的就不做处 ...

  6. Android中内容观察者的使用---- ContentObserver类详解

    详解:http://blog.csdn.net/qinjuning/article/details/7047607

  7. Android 内容观察者的原理

    拦截短信,比如当发短信的时候,就把短信读取出来,当系统的短信发生变化的时候,大叫一声,把数据发送到公共的消息邮箱里面,我们的应用通过内容观察者观察公共的消息邮箱 获取ContentResolver对象 ...

  8. Android开发之内容观察者

    内容观察者: 当关注应用的数据库数据改变时,内容提供者会发出通知,在内容提供者的uri上注册一个内容观察者,就可以收到数据改变的通知 实现步骤: 1.假如是自定义的ContentProvider,需要 ...

  9. Android(java)学习笔记253:ContentProvider使用之内容观察者02

    下面通过3个应用程序之间的交互说明一下内容观察者: 一. 如下3个应用程序为相互交互的: 二.交互逻辑图: 三.具体代码: 1.   16_数据库工程: (1)数据库帮助类BankDBOpenHelp ...

随机推荐

  1. svn使用常用错误

    描述 :SVN更新提交显示文件被锁异常: Working copy XXXXXXXX locked Please execute "Cleanup" command 原因 : 待查 ...

  2. 通过Java代码装配Bean

    上面梳理了通过注解来隐式的完成了组件的扫描和自动装配,下面来学习下如何通过显式的配置的装配bean 二.通过Java类装配bean 在前面定义了HelloWorldConfig类,并使用@Compon ...

  3. eclipse Oxygen 4.7 + pydev

    pydev 官网  安装手册 PyDev requires Java 8 and Eclipse 4.6 (Neon) in order to run and only supports Python ...

  4. 附上SQL Server的存储过程例子

    代码如下,看了就明白: --添加项目大类存储过程 use chaiqianD2 go if object_id('p_InsertBigType', 'p') is not null drop pro ...

  5. 基于NodeJS的14款Web框架

    摘要: 在几年的时间里,Node.js逐渐发展成一个成熟的开发平台,吸引了许多开发者.有许多大型高流量网站都采用Node.js进行开发,像PayPal, 此外,开发人员还可以使用它来开发一些快速移动W ...

  6. 解剖Nginx·模块开发篇(4)模块开发中的命名规则和模块加载与运行流程

    1 命名规则 1.1 基本变量 基本变量有三个: ngx_module_t 类型的 ngx_http_foo_bar_module: ngx_command_t 类型的数组 ngx_http_foo_ ...

  7. ios加载本地html

    UIWebView加载工程本地网页与本地图片 - (void)viewDidLoad { [super viewDidLoad]; NSString *filePath = [[NSBundle ma ...

  8. 配置jdk和tomcat的环境变量

    一.1,新建变量名:JAVA_HOME,变量值:d:\Program Files\Java\jdk1.7.0 2,打开PATH,添加变量值:%JAVA_HOME%\bin;%JAVA_HOME%\jr ...

  9. 276. Paint Fence篱笆涂色

    [抄题]: There is a fence with n posts, each post can be painted with one of the k colors. You have to ...

  10. vi/vim 消除搜索后的关键字高亮

    使用vi或vim命令搜索某个关键字之后,取消高亮显示的方法 只要输入:noh即可