用观察者模式仿EventBus

效果

  1. 在全局任意地方均可发送消息,没类层数限制
  2. 在任意类注册,可接收到消息
  3. 关闭Activity或View可以取消订阅
  4. 可以清晰区分不同任务,指令
使用方法 注册 在任意类进行注册
/** * ObMsgBean.CHAT_ADAPTER 为任务类型,区分不同大块任务 * this 1 : Context ,这里传Context只是取了类名,用于记录,不会引起内存泄漏 * this 2 : 回调接口 */ ObserverTools.getInstance(ObMsgBean.CHAT_ADAPTER).addXNObserver(this, this);

接收消息 【用观察者模式仿EventBus】回调接口
@Override public void onNext(int type, Object... o) throws Exception { switch (type) {// 具体指令 case ChatMsgBean.SHOW_LOADING: // 具体操作 //参数 : o,为数组集合,里面为传过来的参数,至少会有一个参数,为发起命令的类及行号. break; } }

发送消息 在任意位置
// ObMsgBean.CHAT_ADAPTER 为任务类型 // ChatMsgBean.SHOW_LOADING 指令类型 // bmsg.msgID 为传入的参数,动态参数可传多个 ObserverTools.getInstance(ObMsgBean.CHAT_ADAPTER).setMsg(MsgBean.SHOW_LOADING, bmsg.msgID);

解除订阅 删除该任务类型下的所有观察者
ObserverTools.getInstance(ObMsgBean.CHAT_ADAPTER).deleteObservers();

删除该任务类型下的与某个Context相关的观察者
ObserverTools.getInstance(ObMsgBean.CHAT_ADAPTER).deleteContextObservers(context);

删除该任务类型下的指定观察者
ObserverTools.getInstance(ObMsgBean.CHAT_ADAPTER).deleteContextObservers(context);

工具类
/** * 观察者模式工作类 * 全局通知 * Created by guomeng on 2018/4/20. */ @SuppressWarnings("ALL") public class ObserverTools extends Observable{ private final int taskType; private ObMsgBean obMsgBean; /** * 观察者/map集合 * key : 观察者所属的context 名称 * value : 所在context所有的观察者集合 [ key : 每个观察者所实现的接口hash码 * value : 观察者对象 ] */ private ArrayMap> observerMap = new ArrayMap<>(); /** * 被观察者 */ private static SparseArray observables = new SparseArray<>(); private XNObserver xnObserver; /** * 根据任务类型获取相应实例 * * @param taskType 任务类型 * @return */ public static ObserverTools getInstance(int taskType) { ObserverTools inst = null; if (observables.get(taskType) != null) { inst = observables.get(taskType); } else { inst = new ObserverTools(taskType); observables.put(taskType, inst); } return inst; }private ObserverTools(int taskType) { this.taskType = taskType; obMsgBean = new ObMsgBean(); }/** * 添加观察者对象 * * @param context所依赖的context * @param listener 注册的监听对象 * @return this */ public ObserverTools addXNObserver(Context context, OnObserverToolListener listener) { if (listener == null) return null; if (xnObserver == null) xnObserver = new XNObserver(this); xnObserver.setListener(listener); String key = context.toString(); if (observerMap.containsKey(key)) { observerMap.get(key).put(listener.hashCode(), xnObserver); } else { SparseArray xnObservers = new SparseArray<>(); xnObservers.put(listener.hashCode(), xnObserver); observerMap.put(key, xnObservers); } return this; }/** * 删除所有观察者 */ @Override public void deleteObservers() { super.deleteObservers(); observerMap.clear(); observables.remove(taskType); }/** * 删除context相关的观察者对象 * * @param context */ public void deleteContextObservers(Context context) { String key = context.toString(); if (!observerMap.containsKey(key)) { return; } for (int i = 0, nsize = observerMap.get(key).size(); i < nsize; i++) { XNObserver xnObserver = observerMap.get(key).valueAt(i); deleteObserver(xnObserver); } observerMap.remove(key); }/** * 删除指定观察者 * * @param listener 实现观察者所在的类 */ public void disposeObserver(Context context, OnObserverToolListener listener) { if (listener == null || !observerMap.containsKey(context.toString())) return; deleteObserver(observerMap.get(context).get(listener.hashCode())); }public interface OnObserverToolListener { /** * 监听者回调 * * @param type * @param o * @throws Exception */ void onNext(int type, Object... o) throws Exception; }/** * 设置发送消息 * * @param type 动作类型 * @param parm 参数 可多个 */ public void setMsg(int type, Object... parm) { obMsgBean.setType(type); obMsgBean.setPath("文件 : " + getCurrentFileName() + " 行号 : " + _LINE_()); for (int i = 0; i < parm.length; i++) obMsgBean.setMsg(parm[i]); setChanged(); notifyObservers(obMsgBean); }// 当前文件名 private static String getCurrentFileName() { StackTraceElement traceElement = ((new Exception()).getStackTrace())[3]; return traceElement.getFileName().replace(".java", ""); }// 当前行号 private static int _LINE_() { StackTraceElement traceElement = ((new Exception()).getStackTrace())[3]; return traceElement.getLineNumber(); }/** * 观察者内部类 */ public class XNObserver implements Observer { ArrayList listeners; public XNObserver(Observable observable) { listeners = new ArrayList<>(); observable.addObserver(this); }@Override public void update(Observable observable, Object value) { ObMsgBean obMsgBean = (ObMsgBean) value; Object[] objects = new Object[obMsgBean.getMsg().size() + 1]; for (int i = 0; i < obMsgBean.getMsg().size(); i++) { objects[i] = obMsgBean.getMsg().get(i); } objects[obMsgBean.getMsg().size()] = obMsgBean.getPath(); try { for (int i = 0; i < listeners.size(); i++) { listeners.get(i).onNext(obMsgBean.getType(), objects); } } catch (Exception e) { e.printStackTrace(); } }public void setListener(OnObserverToolListener listener) { if (!listeners.contains(listener)) listeners.add(listener); } } }

消息实体类和任务类型
/** * 使用观察者模式时的消息Bean * Created by boyko on 2017/5/6. */ public class ObMsgBean { /** * 任务类型 / ****** *//** * 聊天页面和适配器/聊天列表的交互 */ public static int CHAT_ADAPTER = 100; /** * 设置主题与聊天头像交互 */ public static int CHAT_AVATAR = 101; /** * 触发观察者时,传递的消失类型 */ int type; /** * 发送改消息bean的方法路径 */ String path; ArrayList list = new ArrayList(); public int getType() { return type; }public void setType(int type) { cleanData(); this.type = type; }private void cleanData() { type = 0; list.clear(); }public String getPath() { return path; }public void setPath(String path) { this.path = path; }public void setMsg(Object msg) { list.add(msg); }public ArrayList getMsg() { return list; } }
指令类
public class MsgBean {/** * 显示头像loading */ public static final int SHOW_LOADING = 1000; /** * 隐藏头像loading */ public static final int HINT_LOADING = 1001; /** * 更换主题刷新头像 */ public static final int REFRESH_AVATAR = 1003; /** * 当内容加载完成,listview拉到最底部 */ public static final int PULL_BOTTOM = 1002; }

如有不足,请指正.

    推荐阅读