一个单线程的ContentObserver的Demo

先看图,因为这个DEMO是一个单线程,只是实现了观察者模式的基础,所以只有一个activity,并且代码不多

思路是这样的,通过观察者模式,监听SMS短信数据库的变化,从而完成一个数据自动加载的功能

这是Activity的展示,里面就一个EditText,测试的时候我会通过模拟器发送一条短信,然后这里会显示短信的内容,我就不贴xml代码了,只有一个控件



好了接下来就是主角登场,我一边贴代码,一边解释

    private SMS_Observer smsObserver;
    EditText et_input;
    Handler handler;
    ContentResolver resolver;

SMS_Observer是一个继承了ContentObserver的类,一会我会展开

ContentResolver是一会用来查询数据库的

还有一个Uri静态变量类,方便调用

public class UriContent {
    //短信数据
    public static String SMS = "content://sms";
    //收件箱数据
    public static String SMS_INBOX = "content://sms/inbox";
}
然后就是实例化我们所需要的元素

 //handler创建,实现接口,返回值如果为false,表示不需要进行任何的处理,所以一般都返回true
        handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                if(msg.what == 100)
                {
                    et_input.setText(msg.obj.toString());
                }
                return true;
            }
        });
        //实例化
        resolver = getContentResolver();
        smsObserver = new SMS_Observer(handler, this);
这里大家看到Handller构造的时候需要一个Callback接口,并实例化

    public interface Callback {
        public boolean handleMessage(Message msg);
    }
我们实例化的这个handleMessage函数,是用来接收我们刚刚创建的那个Handler变量的sendMessage函数,之后会看到。

我这里的理解就是自己发,自己收,因为Obersoer实例化的时候需要传入一个Handler。

然后就是注册了,如果不注册,他就无法监听数据库啦

//对观察者进行注册
        //第一个参数:是一个Uri(Uri就是一个绝对路径)
        //“content://sms”是短信的数据库
        //“content://sms/inbox”是短信收件箱
        //我会把这两个字段定义成一个类的静态成员方便调用
        //第二个参数是个布尔值,表示是否递归,如果为true说明当前Uri路径下的任何变化都会捕捉,如果为false说明只捕捉当前的Uri路径,不包括子路径
        //地三个参数就是一个观察者
        resolver.registerContentObserver(Uri.parse("content://sms"), true, smsObserver);
        /**
         * 来理一下思路
         * 首先在页面创建的时候,创建一个Observer,并通过resolver注册这个Observer,Observer被注册后,会监听给定URI路径下的数据,
         * 如果数据发生变化,就会通过Observer里的handler进行处理
         */

参数我已经讲的很清楚了,就不一一解释了,然后有注册那就还会有销毁

@Override
    protected void onDestroy() {
        super.onDestroy();
        resolver.unregisterContentObserver(smsObserver);
    }

Activity的代码就解释完了,我把代码完整的发一遍

package com.ty.contentobserver_demo1;

import android.content.ContentResolver;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.EditText;

import com.ty.contentobserver_demo1.util.Observer.SMS_Observer;

public class MainActivity extends AppCompatActivity {
    private SMS_Observer smsObserver;
    EditText et_input;
    Handler handler;
    ContentResolver resolver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        et_input = (EditText) findViewById(R.id.ET_Main_Input);

        //handler创建,实现接口,返回值如果为false,表示不需要进行任何的处理,所以一般都返回true
        handler = new Handler(new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                if(msg.what == 100)
                {
                    et_input.setText(msg.obj.toString());
                }
                return true;
            }
        });
        //实例化
        resolver = getContentResolver();
        smsObserver = new SMS_Observer(handler, this);
        //对观察者进行注册
        //第一个参数:是一个Uri(Uri就是一个绝对路径)
        //“content://sms”是短信的数据库
        //“content://sms/inbox”是短信收件箱
        //我会把这两个字段定义成一个类的静态成员方便调用
        //第二个参数是个布尔值,表示是否递归,如果为true说明当前Uri路径下的任何变化都会捕捉,如果为false说明只捕捉当前的Uri路径,不包括子路径
        //地三个参数就是一个观察者
        resolver.registerContentObserver(Uri.parse("content://sms"), true, smsObserver);
        /**
         * 来理一下思路
         * 首先在页面创建的时候,创建一个Observer,并通过resolver注册这个Observer,Observer被注册后,会监听给定URI路径下的数据,
         * 如果数据发生变化,就会通过Observer里的handler进行处理
         */
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        resolver.unregisterContentObserver(smsObserver);
    }
}
第二部分,也就是SMS_Observer这个类,既然监听回掉的是Observer的OnChange这个函数,自然我们要重写一下这个函数,告诉他应该做点啥

1、我们先看SMS_Observer这个类的变量和构造函数

    private ContentResolver resolver;
    private Handler handler;
    public SMS_Observer(Handler handler, Context context) {
        super(handler);
        resolver = context.getContentResolver();
        this.handler = handler;
    }
Resolver我就不具体讲了,之前一片博客已经写过了。

然后就是onChange这个函数的重写

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        Cursor cursor = resolver.query(Uri.parse(UriContent.SMS_INBOX), new String[]{"body"}, null, null, "date desc");
        if(cursor != null)
        {
            if(cursor.moveToFirst())
            {
                String smsBody = cursor.getString(0);
                Message msg = Message.obtain();
                msg.what = 100;
                msg.obj = smsBody;
                handler.sendMessage(msg);
                cursor.close();
            }
        }
    }
重点其实就是只有一句话

handler.sendMessage(msg);
先定义一个Message然后赋值最后发送

说是发送,其实就是加入一个消息的队列

我们之前的那个handleMessage函数一直在查询队列里有没有消息

我再把他贴上来对比一下

public boolean handleMessage(Message msg) {
    if(msg.what == 100)
    {
        et_input.setText(msg.obj.toString());
    }
    return true;
}
大家这下应该就差不多清楚了,应为我其实还没学习到怎么熟练的使用handler,这篇就当是一个引导,之后还会有更详细更深入的讲解

我再把代码贴一下这个类的完整代码贴一下

package com.ty.contentobserver_demo1.util.Observer;

import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;

import com.ty.contentobserver_demo1.util.Observer.Uri.UriContent;

/**
 * Created by IT on 2017/2/23.
 */

public class SMS_Observer extends ContentObserver {

    private ContentResolver resolver;
    private Handler handler;
    public SMS_Observer(Handler handler, Context context) {
        super(handler);
        resolver = context.getContentResolver();
        this.handler = handler;
    }

    @Override
    public void onChange(boolean selfChange) {
        super.onChange(selfChange);
        Cursor cursor = resolver.query(Uri.parse(UriContent.SMS_INBOX), new String[]{"body"}, null, null, "date desc");
        if(cursor != null)
        {
            if(cursor.moveToFirst())
            {
                String smsBody = cursor.getString(0);
                Message msg = Message.obtain();
                msg.what = 100;
                msg.obj = smsBody;
                handler.sendMessage(msg);
                cursor.close();
            }
        }
    }
}


好了   我还会回来的





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值