内容提供者应用暴露的数据,是被多个其他应用访问(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理解为:广播, 只是代码和广播不一样而已

最新文章

  1. Hack语言特性之类型化
  2. 【Java环境变量的配置问题】
  3. asp.net mvc 4 json大数据异常 提示JSON字符长度超出限制的异常
  4. Java Annotation原理分析(一)
  5. ZMMR107-批量更改PO经价值
  6. Android新浪微博客户端(四)——添加多个账户及认证
  7. android -上传文件到服务器
  8. mysql JDBC总结
  9. OpenTSDB-Querying or Reading Data
  10. 无预挖无ICO-潜力币XDAG最强攻略
  11. 牛客小白月赛12 H(dfs序+线段树),F(分块思想+bit),J(二分)
  12. Lock锁与Condition监视器(生产者与消费者)。
  13. 用node搭建本地服务环境
  14. hdoj:2072
  15. centos打开matlab的正确姿势
  16. mezzanine的page_menu tag(二)
  17. 大数据之 Spark
  18. 电脑出现 flash update failed 解决方法
  19. Java集合(续)
  20. python之模块csv之CSV文件一次写入多行

热门文章

  1. 微信浏览器清缓存、cookie等
  2. mybatis No enum const class org.apache.ibatis.type.JdbcType.Date 坑爹的配置
  3. addClass()使用方法
  4. 配置python的豆瓣source
  5. RedHat Linux设置yum软件源为本地ISO
  6. Unity中Avatar换装实现
  7. Sqlserver2008 FileStream解决图片存储问题
  8. 文件操作getc
  9. 全新的css网站布局--Grid布局
  10. UML建模之类图