资讯专栏INFORMATION COLUMN

Android设计模式之观察者模式

kid143 / 318人阅读

摘要:因此我们知道,观察者模式中主要有观察者和被观察者个对象,而在观察模式中表示被观察者,由于这个对象是一个抽象类,所以只能被继承。

观察者模式(Observer Pattern)
定义对象间的一种一个(Observable)对多(Observer)的依赖关系,当一个对象的状态发送改变时,所以依赖于它的对象都得到通知并被自动更新。
当然,MVC只是Observer模式的一个实例。
Observer模式要解决的问题为:建立一个一(Observable)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个“一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。Observer模式就是解决了这一个问题。
因此我们知道,观察者模式中主要有观察者和被观察者2个对象,而在观察模式中Observable表示被观察者,由于这个对象是一个抽象类,所以只能被继承。而Observer表示观察者,它并不是一个类而是一个接口,所以观察者可以有多个,实现了该接口的类都属于观察者。 当然有人会问既然被观察者是一个抽象类而观察者是一个接口,那么是否有一个类即继承Observable类又实现Observer接口呢,这个自然可以,观察者当然也可以同时是被观察者,被观察者同样可以是观察者,在这里完全不冲突。
当某一个我们需要被观察的对象继承自Observable类时,就表示该类可以被很多观察者(实现了Observer)观察,其实意思就是说这个对象也就是被观察者“上电视了”,电视前的你也就是观察者可以看,(对象发生变化)电视里被观察者做了别的动作,那么电视前的所有人看到的也就变了,在同一时间改变所有观众看到的画面。

观察者模式的适用性:
当一个抽象模型有两个方面,其中一个方面依赖于另一方面,将这两者封装成独立的对象中以使它们可以各自独立的改变和服用
当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变
当一个对象必须通知其它对象,而它又不能假定其它对象是谁

观察者模式的参与者:
Observable(目标也叫被观察者)
目标知道它的观察者,可以有任意多个观察者观察同一个目标
提供注册和删除观察者对象的接口
Observer(观察者)
为那些在目标发生改变时需获得通知的对象定义个更新的接口
ConcreteObservable(具体目标)
将有关状态存入各ConcreteObserver对象
当它的状态发送改变时,向它的各个观察者发出通知
ConcreteObserver(具体观察者)
维护一个指向ConcreteObserver对象的引用
存储有关状态,这些状态应与目标的状态保持一致
实现Observer的更新接口是自身状态与目标的状态保持一致

Android 项目开发实战:短信验证码自动填写
ContentObserver
内容观察者,目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当 ContentObserver 所观察的Uri发生变化时,便会触发它。
观察特定Uri的步骤如下:
创建我们特定的 ContentObserver 派生类,必须重载父类构造方法,必须重载 onChange() 方法去处理回调后的功能实现。
利用 context.getContentResolover() 获得 ContentResolove 对象,接着调用 registerContentObserver() 方法去注册内容观察者。
由于 ContentObserver 的生命周期不同步于 Activity 和 Service 等,因此,在不需要时,需要手动的调用 unregisterContentObserver() 去取消注册。

SmsObserver.java
package com.shijiacheng.verificationcode;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;

public class SmsObserver extends ContentObserver {

    private Context mContext;
    private Handler mHandler;

    public SmsObserver(Context context, Handler handler) {
        super(handler);
        mContext = context;
        mHandler = handler;
    }
/**
 * 接收到短信时调用此方法
 */

 

  

    @Override
        public void onChange(boolean selfChange, Uri uri) {
            super.onChange(selfChange, uri);
    
            Log.d("DEBUG", "SMS has changed!");
            Log.d("DEBUG", uri.toString());
    
            if (uri.toString().equals("content://sms/raw")) {
                return;
            }
    
            Uri inboxUri = Uri.parse("content://sms/inbox");
            Cursor cursor = mContext.getContentResolver().query(inboxUri, null,
                    null, null, "date desc");
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    String address = cursor.getString(cursor
                            .getColumnIndex("address"));
                    String body = cursor.getString(cursor.getColumnIndex("body"));
                    Log.d("DEBUG", "发件人为:" + address + " " + "短信内容为:" + body);
    
                    // if (!address.equals("你的公司的手机号")) {
                    // return;
                    // }
    
                    Pattern pattern = Pattern.compile("(d{6})");//正则表达式
                    Matcher matcher = pattern.matcher(body);
                    if (matcher.find()) {
                        String code = matcher.group(0);
                        Log.d("DEBUG", "code is" + code);
    
                        mHandler.obtainMessage(MainActivity.MSG_RECEIVED_CODE, code)
                                .sendToTarget();
                    }
                }
            }
    
        }
    
    }
MainActivity.java
package com.shijiacheng.verificationcode;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.widget.EditText;
public class MainActivity extends Activity {
    public static final int MSG_RECEIVED_CODE = 1;
    private EditText etVerficationCode;
    private SmsObserver mObserver;
    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (msg.what == MSG_RECEIVED_CODE) {
                String code = (String) msg.obj;
                etVerficationCode.setText(code);
            }
        };
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        etVerficationCode = (EditText) findViewById(R.id.et_verification_code);
        mObserver = new SmsObserver(MainActivity.this, mHandler);
        Uri uri = Uri.parse("content://sms");
        getContentResolver().registerContentObserver(uri, true, mObserver);
    }
    @Override
    protected void onPause() {
        super.onPause();
        getContentResolver().unregisterContentObserver(mObserver);
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/13128.html

相关文章

  • Android中的设计模式察者模式

    摘要:反正我觉得自己手写,懒得写,经常见到的情况是一个来处理多个子线程发来的消息,不是就是还要做一些变换啥的,还要考虑有没有内存泄漏情况,子线程任务要能及时取消等等有点烦,除非你设计好了一个良好的封装。 参考 《设计模式:可复用面向对象软件的基础 》5.7 Observer 观察者 对象行为型模式 《设计模式解析》 18.4 Observer模式 《Android源码设计模式解析与实战》第...

    habren 评论0 收藏0
  • AndroidRxJava详解

    摘要:在事件处理过程中出异常时,会被触发,同时队列自动终止,不允许再有事件发出。行为模式和差不多,区别在于的内部实现是是用一个无数量上限的线程池,可以重用空闲的线程,因此多数情况下比更有效率。这个使用的固定的线程池,大小为核数。文章大纲 一、什么是RxJava二、为什么要用RxJava三、RxJava使用详解四、项目源码下载五、参考文章 一、什么是RxJava   Rx(Rea...

    番茄西红柿 评论0 收藏0
  • RxJava 源码解析察者模式

    摘要:传统观察者模式观察者模式面向的需求是对象观察者对对象被观察者的某种变化高度敏感,需要在变化的一瞬间做出反应。如下图而作为一个工具库,使用的就是通用形式的观察者模式。这是为了方便以上就是最基本的一个通过观察者模式,来响应事件的原理。 了解 RxJava 的应该都知道是一个基于事务驱动的库,响应式编程的典范。提到事务驱动和响应就不得不说说,设计模式中观察者模式,已经了解的朋友,可以直接跳过...

    Steve_Wang_ 评论0 收藏0
  • 代码 - 收藏集 - 掘金

    摘要:行代码的人脸识别实践产品掘金前言很多人都认为人脸识别是一项非常难以实现的工作,看到名字就害怕,然后心怀忐忑到网上一搜,看到网上页的教程立马就放弃了。掘金最新最全的开源项目合集掘金是由整理并维护的安卓相关开源项目库集合。 安卓第三方登录之微信登录(图文详解) - Android - 掘金一、创建应用并成为开发者 1、创建应用 1)到微信开放平台管理中心,点击创建移动应用 ... 三步实现...

    neuSnail 评论0 收藏0
  • Android】RxJava初始篇

    摘要:关于是推出在环境下使用的异步操作库。被观察者使用需要创建,用于发射数据。发射,可以表示发射事件结束。控制的线程,也可以说是控制事件被执行时所在的线程。输出结果操作符表示跳过前几个事件从某一个事件开始发射事件,下标从开始。 关于RxJava RxJava是ReactiveX推出在Java VM环境下使用的异步操作库。除了在Java环境ReactiveX也为其他编程语言推出Rx库,例如Py...

    Alex 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<