ContentProvider和Observable 以及观察者模式


        用Android 的ContentObserver 来在你的代码中监听数据的变化

        最近在公司里面的项目发现 要监听某个数据的变化,但是这个数据又是另外一个应用提供的,场景描述为:一个计步器的应用,会用sensor感应到你的步数,而在另外一个应用中,要展示出你今天所走的步数。

用到的Android 知识:  
ContentProvider(这货不是Android的四大组件之一么,终于用上了) 和 ContentObserver  (看到了Observer,想到了观察者模式,所以顺便也把观察者模式也给补了)

ContentProvider:  
        从字面意思就可以看到它是内容提供者,那么在app 中传递的东西当然就是各种各样的数据了,就像在网络中传递的数据一样,现在是从一个应用提供出来的,那么数据要找个地方存储,文件,sharedpreference 都可以存储,但是访问方式就不能统一(参考: http://www.cnblogs.com/linjiqin/archive/2011/05/28/2061396.html ),统一数据的访问方式当然要使用数据库了,mysql 的小巧便捷我可是记得哦,各种select语句也跟有魔法一样取出你想要的数据,不过当多表关联的时候,也会很麻烦,言归正传,Android里的数据库比较特殊,它就是sqlLite,对于它的使用以我目前所掌握的知识来看,也是很简单的,继承相应的接口,写写sql 语句,想必一般的功能是不成问题的,而ContentProvider 一般都是跟SqlLite 一起使用的 。

    首先在AndroidManifest里面配置ContentProvider, 最主要是定义它的URI,作为外部访问的标识。
< manifest....  >
< application  android:icon ="@drawable/icon"  android:label ="@string/app_name" >
< provider  android:name =".PersonContentProvider"  
android:authorities
="com.ljq.providers.personprovider" />
</ application >
</ manifest >
       使用ContentProvider ,自定义类继承ContentProvider,重写其中的方法

   public class PersonContentProvider extends ContentProvider{
   public boolean onCreate()
   public Uri insert(Uri uri, ContentValues values)
   public int delete(Uri uri, String selection, String[] selectionArgs)
   public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)
   public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)
   public String getType(Uri uri)
}
       如果存储到数据库,在具体的方法里面进行数据库的操作,可以在此写一个内部类继承SQLiteOpenHelper 
<后补SqlLite的用法>
   
       既然用URI来标识,那么必然有一定的规范,像是spring框架中的action的URL,后缀一般都有一定含义,URL作为其中一种URI,广泛用于网络通信中,http协议定义的URL想必大家都熟悉。在这里,一般都会用到Uri.parse()这样的函数将一段字符串解析成uri,通常还会有类似字符串的一些既定函数提供使用,比如添加了,判断匹配了之类。
        使用时,需要取得ContentResolver对象,用此对象对ContentProvder 操作,ContentResolver 一般是通过 getContentResovler 方法获得,具有下列方法:

public Uri insert(Uri uri, ContentValues values):该方法用于往ContentProvider添加数据。
public int delete(Uri uri, String selection, String[] selectionArgs):该方法用于从ContentProvider删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs):该方法用于更新ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder):该方法用于从ContentProvider中获取数据。

          如同工作环境中所提,这里不仅仅是将数据存储,还要通知数据的变化,因此像通知adapter里面的item数据变化一样,需要一个notify函数( 我臆测其源码是某个线程阻塞,等待该线程的notify,不是这样的,仅仅是一个回调而已)
         getContext().getContentResolver().notifyChange( Uri,  null ); 
ContentObserver:
      有了Provider ,那么监听者是谁呢,就是ContentObserver 
      仍然自定义类继承ContentObsever, 注意它自带的 Handler 变量(handler的机制,有关于和Loop,ThreadLocal的关系等,依然很迷人哦~),这个Hander 就是用于当监听到了数据,更新到UI上去的,当然你的Handler最好是UI线程上传递过来的,因为你监测了变化,大部分都是需要作出相应的动作的,否则你监听干嘛。
       那么怎么监听到呢?
       依然用到 ContentResolver这个变量,看来是老大啊, 注册你的observer,这个一般都是在Mainactivity或者初始化设置的时候进行的
   getContentResolver().registerContentObserver(uri, true,yourObserver)  

然后就是 Observe里面重写的onChange()方法, 你会在这里得到你想要监测的数据,写法是:
Cursor c = mContext.getContentResolver().query(uri,  null null null , "date desc" ); //参数是你要求的数据
获得的是一个数据集

对它循环遍历,存储到一个数据结构中。
然后将数据通过handler 发到UI线程上去处理
mHandler.obtainMessage(MSG_FLAG, data.toString()).sendToTarget();          

然后就是handler 里面handlemessage的处理

    最后的最后,不要忘记unregister你的observer
getContentResolver().unregisterContentObserver(yourObserver)  


有关于Observer的缺点:对所监测的数据不能提供额外的信息,从而导致provider在提供数据变化的时候,会重复读所有的记录,从而浪费资源? 还需要进一步消化,获知于 http://www.grokkingandroid.com/use-contentobserver-to-listen-to-changes/

观察者模式


被观察者(subject) 和 观察者(observer) 两个接口,  subject 里面一般会维护很多observer, 如Arraylist 来维护,然后里面会用函数来一一通知所有的observer(notify 函数),即回调 observer里面的相应函数,对其进行改变。
observer 里面只需要将 改变展示出来即可。
但是看到有推拉模式的区别,估计应该都是使用拉模式,在observer 里面会将subject对象取得,然后去取得自己需要的数据。
Java 提供 了 状态模式的支持,有Observable 类 和  Observer 接口













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值