一个类实现Android观察者模式(最简单实用的观察者模式)

来源:互联网 发布:日本产假多少天 知乎 编辑:程序博客网 时间:2024/05/22 04:27

本篇为大家介绍一下观察者模式。


这里不会再画那些无聊的关系图,类图。因为观察者模式非常简单,那些图网上到处都是,连百度百科都已经有很长的内容了。


简单的说一下逻辑:当某事件(Event)被任何地方触发的时候,这个事件的所有监听者(Listener),都会触发监听器。

当然,这个事件也可能没有一个监听者,但他并不关心这个。


先来看看公共处理逻辑类

package com.chenjian.observer;import android.content.Intent;import java.lang.ref.SoftReference;import java.util.ArrayList;import java.util.HashMap;import java.util.Map;/** * Created by ChenJian * 2016.8.3 16:48:48. */public class SystemEvent {    private static Map<SystemEventConst, ArrayList<SoftReference<EventListener>>> mEventMap = new HashMap<>();    public static void release() {        if (mEventMap != null) {            for (Map.Entry<SystemEventConst, ArrayList<SoftReference<EventListener>>> entry : mEventMap.entrySet()) {                if (entry.getValue() != null) {                    entry.getValue().clear();                }            }            mEventMap.clear();            mEventMap = null;        }    }    public interface EventListener {        void onEvent(SystemEventConst eventType, Intent data);    }    public synchronized static boolean addListener(SystemEventConst eventType, EventListener eventListener) {        if (mEventMap == null) {            return false;        }        ArrayList<SoftReference<EventListener>> list = mEventMap.get(eventType);        if (list == null) {            list = new ArrayList<>();        }        for (SoftReference<EventListener> softListener : list) {            if (softListener != null) {                EventListener sEventListener = softListener.get();                if (sEventListener != null && sEventListener == eventListener) {                    return false;                }            }        }        SoftReference<EventListener> listener = new SoftReference<>(eventListener);        list.add(listener);        mEventMap.put(eventType, list);        return true;    }    public synchronized static void removeListener(SystemEventConst eventType, EventListener listener) {        ArrayList<SoftReference<EventListener>> list = mEventMap.get(eventType);        if (null == list) {            return;        }        for (int i = 0; i < list.size(); i++) {            EventListener l = list.get(i).get();            if (l == listener) {                list.remove(i);                break;            }        }    }    public synchronized static void removeListener(SystemEventConst eventType) {        mEventMap.remove(eventType);    }    public synchronized static void fireEvent(SystemEventConst eventType, Intent data) {        ArrayList<SoftReference<EventListener>> list = mEventMap.get(eventType);        if (list != null) {            for (int i = 0; i < list.size(); i++) {                EventListener listener = list.get(i).get();                if (listener != null) {                    listener.onEvent(eventType, data);                }            }        }    }    public synchronized static void fireEvent(SystemEventConst eventType) {        fireEvent(eventType, null);    }}
这个类中,保存着一个map,key为事件类型,value是这个事件所对应的监听器列表。

本类中也包含了一些添加删除监听器的方法,同样也有触发事件的方法。

触发事件时,可以不带参数,带参数的话,这里选择的是Intent类型,我不用Map而用Intent,因为个人感觉Intent更符合Android的数据传递思想。


再来看看事件类型,SystemEventConst类

package com.chenjian.observer;/** * Created by ChenJian * 2016.8.3 16:48:48. */public enum SystemEventConst {    /**     * 总金额变化     */    EVENT_TOTAL_MONEY_CHANGE,}

是一个枚举类型,里面可以定义自己想要的事件。


再来看看使用


主界面布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin">    <TextView        android:id="@+id/tv_main_money"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="@string/money" />    <Button        android:id="@+id/btn_main"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_marginTop="30dp"        android:text="@string/button" /></LinearLayout>

代码

package com.chenjian.observer;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity implements SystemEvent.EventListener {    private TextView mMoneyTextView;    private Button mButton;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findView();        setListener();    }    @Override    protected void onDestroy() {        super.onDestroy();        SystemEvent.removeListener(SystemEventConst.EVENT_TOTAL_MONEY_CHANGE, this);    }    private void findView() {        mMoneyTextView = (TextView) findViewById(R.id.tv_main_money);        mButton = (Button) findViewById(R.id.btn_main);    }    private void setListener() {        mButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                startActivity(new Intent(MainActivity.this, OtherActivity.class));            }        });        SystemEvent.addListener(SystemEventConst.EVENT_TOTAL_MONEY_CHANGE, this);    }    @Override    public void onEvent(SystemEventConst eventType, Intent data) {        switch (eventType) {            case EVENT_TOTAL_MONEY_CHANGE:                mMoneyTextView.setText(data.getAction());                break;        }    }}

TextView上显示金额,按钮点击后跳转到另一个界面。

这里使用到了观察者模式,在一开始的时候,注册了监听器,在事件发生的时候,改变金额的值。

要非常注意的是:在监听者被销毁不再使用的时候,要把自己从监听器列表中删除掉


再来看看OtherActivity

package com.chenjian.observer;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.os.Handler;/** * 作者: ChenJian * 时间: 2016.12.28 10:42 */public class OtherActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Intent intent = new Intent("$110");        SystemEvent.fireEvent(SystemEventConst.EVENT_TOTAL_MONEY_CHANGE, intent);        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                finish();            }        }, 3000);    }}

触发事件,并带上金额的参数,三秒后退出。


看看前后界面显示




Android中观察者模式还是相对常用的,比如本例,在主界面或者其它页面都可能显示着用户的个人信息,金额昵称之类的,在详情页或者修改页去做修改后,通知相关页面做出修改。如果使用BrocastReceiver或者全局变量,就显得非常的麻烦。


源码下载点击打开链接

1 0
原创粉丝点击