ContentObserver(观察者模式)

最近做项目时,用户频繁切换账号需更新数据,一开始用的是广播,广播会有延迟后来老大指点用了ContentObserver(观察者模式)。

下面是写了个小Demo

MainActivity



package com.example.contentobserverdemo;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;


public class MainActivity extends Activity {
    private UserContentObserver observer;
    private Uri uri;
    private TextView text;
    private Button btn;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        observer = new UserContentObserver(this, handler);
        uri = Provider.CONTENT_URI_CHANEGE;
        // 注册监听器
        getContentResolver().registerContentObserver(uri, false, observer);
        text = (TextView) findViewById(R.id.text);
        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new OnClickListener() {


            @Override
            public void onClick(View arg0) {
                getContentResolver().notifyChange(uri, null);
            }
        });


    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }


    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (0 == msg.what) {
                text.setText((String) msg.obj);
            }
        };
    };


    // 不用时解除广播

    protected void onDestroy() {

        super.onDestroy();

        getContentResolver().unregisterContentObserver(observer);
    };
}

UserContentObserver:

package com.example.contentobserverdemo;


import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;


public class UserContentObserver extends ContentObserver {
    private Context context;
    private Handler handler;


    public UserContentObserver(Context context, Handler handler) {
        super(handler);
        this.context = context;
        this.handler = handler;
    }


    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        handler.obtainMessage(0, "测试一下ContentObserver").sendToTarget();
    }
}

provider:

public class Provider {
    private static final String Authority = "com.example.contentobserverdemo";
    public static final Uri CONTENT_URI_CHANEGE = Uri.parse("content://" + Authority
            + "/datachange");


}


总结: 使用ContentObserver的情况主要有一下两者情况:

              1、需要频繁检测的数据库或者某个数据是否发生改变,如果使用线程去操作,很不经济而且很耗时 ;

              2、在用户不知晓的情况下对数据库做一些事件,比如:悄悄发送信息、拒绝接受短信黑名单等;

 

  在这两种情形下,使用ContentObserver无疑是最好的利刃了。

 



     ///////////////////////////////////////////////////////////////////////////////////////

     // 重要补充  ---- > ContentObserver监听原理说明

    ///////////////////////////////////////////////////////////////////////////////////////  


      为什么数据改变后会回调至ContentObserver ? 为什么我们自义的ContentProvider数据源发生改变

  后,有监听到任何反应 ? 这与系统的回调系统逻辑有关。

 

      每个ContentProvider据源发生改变后,如果想通知其监听对象, 例如ContentObserver时,必须在其对应方法 update / 

  insert / delete时,显示this.getContentReslover().notifychange(uri , null)方法,回调监听处理逻辑。否则,我们

  的ContentObserver是不会监听到数据发生改变的。 具体原理,大家可以参考老罗的这篇章:

                     Android应用程序组件Content Provider的共享数据更新通知机制分析 

   

      PS:老罗关于ContentProvider的原理分析还是很给力的,大家可以认真看看老罗这个系列,照着源代码,仔细分析下。



            额外补充,最后强烈建议构造ContentObserver对象时,传递主线程所在的Handler,如下:

 

[java]  view plain copy print ?
  1. airplaneCO = new AirplaneContentObserver(this, mHandler); // mHandler为UI线程的Handler对象  

        否则,在更新UI时,可能会报异常(非UI线程更新UI时,即SecurityException)。系统级的进程,会导致

   重启手机。或者在onChange()方法中,使用Handler类相关方法,回调到UI线程更新UI视图。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值