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

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


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


简单的说一下逻辑:当某事件(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或者全局变量,就显得非常的麻烦。


源码下载点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值