美文网首页Android通信
简易App内部消息通信

简易App内部消息通信

作者: ZZombiee | 来源:发表于2018-07-04 11:41 被阅读12次

    之前文章介绍了用广播去通知界面更新,这会儿又无法满足我的要求

    广播进行消息通信

    广播的好处

    • 不需要创建消息类型实体便可一对多或是一对一发送
    • 系统内置,兼容性好

    我现在又为什么不满足于广播?

    • 我只能进行简单的收发,时间久了以后,具体的行为无法获知
    • 无法传递非序列号对象
    • 广播较重
    • 耦合度不高不好扩展

    我的需求

    • 和广播一样,这个消息要一对一发送(或者一对多发送)
    • 同时,我不想建大量的消息类型(即使这个类型是个空属性)
    • 再者,我需要知道他是什么具体的行为,以便以后回溯
    • 我可以传递非序列号的对象

    为此我需要打的地基

    • 全局状态树Store
    • 界面需要观察的行为property
    • 界面根据行为进行响应responder
    • 行为的分发器DispatchManager

    大致的结构


    目录结构.png

    Show Code!

    /**
     * Created by Gss on 2018/2/12 0012.
     */
    
    public abstract class BaseStore<T, E extends BaseResponder> {
        public final ArrayList<E> observerList = new ArrayList();
        private static BaseStore INSTANCE;
    
        public void registerObserver(E t) {
            if (checkValid(t))
                observerList.add(t);
        }
    
        private boolean checkValid(E t) {
            return t != null;
        }
    
        public void unRegisterObserver(E t) {
            if (checkValid(t) && observerList.contains(t))
                observerList.remove(t);
        }
    
        public abstract void notifyObservers(T t, Object objects);
    }
    

    Store目的很简单,将观察者一一添加到集合里
    观察者必须实现接口Responder

    /**
     * Created by Gss on 2018/2/12 0012.
     */
    
    public interface BaseResponder<T> {
        void receiveResponse(T t);
    
        String[] bindAction();
    }
    

    只有两个方法,需要观察的行为(数组返回),响应receiveResponse(重载后面会有)

    /**
     * Created by Gss on 2018/2/12 0012.
     */
    
    public abstract class DispatchManager<T extends ActionType> {
        public void dispatch(int type) {
            dispatch(type, null);
        }
    
        public abstract void dispatch(int type, Object data);
    }
    

    行为管理器,一个是带参数的方法,一个是不带参数的方法

    以上是基类的简易结构,具体实现全在GlobalStore中,如下

    /**
     * Created by Gss on 2018/2/12 0012.
     */
    
    public class GlobalStore extends BaseStore<Action, Responder> {
        private static GlobalStore store;
        private Map<Responder, Map<Class, Method>> responderMethod = new HashMap<>();
    
        public static GlobalStore getStore() {
            if (store == null) {
                store = new GlobalStore();
            }
            return store;
        }
    
        @Override
        public void notifyObservers(Action action, Object objects) {
            if (objects != null)
                action.getAction().setData(objects);
            postMessage(action, objects);
        }
    
        @Override
        public void unRegisterObserver(Responder t) {
            super.unRegisterObserver(t);
            responderMethod.remove(t);
        }
    
        private void postMessage(Action action, Object objects) {
            try {
                for (Responder responder : observerList) {
                    for (String s : responder.bindAction())
                        if (s.equals(action.getAction().getAction())) {
                            String o = CUtil.getInterfaceType(responder);
                             if (objects == null || (objects != null && objects.getClass().getSimpleName().equals(o))) {
                                responder.receiveResponse(objects);
                            }
                            //如类型不对,则查找观察者是否有重载的方法
                            else if (responderMethod.get(responder) == null || responderMethod.get(responder).get(objects.getClass()) == null) {
                                getMethod(responder, objects);
                            }
                            //如类型不对,且map中已存储了map
                            else if (responderMethod.get(responder).get(objects.getClass()) != null) {
                                responderMethod.get(responder).get(objects.getClass()).invoke(responder, objects);
                            } else
                                responder.receiveResponse(null);
                            break;
                        }
                }
            } catch (Exception e) {
            }
        }
    
        private boolean getMethod(Responder responder, Object c) {
            try {
                Method m = responder.getClass().getMethod("receiveResponse", c.getClass());
                m.invoke(responder, c);
                if (responderMethod.get(responder) == null)
                    responderMethod.put(responder, new HashMap<Class, Method>());
                responderMethod.get(responder).put(c.getClass(), m);
                return true;
            } catch (Exception e) {
                responder.receiveResponse(null);
            }
            return false;
        }
    
    }
    

    方法体含义

    • postMessage,遍历观察者集合,从集合中再去获取观察的行为数组进行遍历,如果发出的行为匹配了观察者需要观察的行为,调用responder里的receiveResponse通知界面进行相应操作。
    • getMethod,如上responder中没有接收相应参数的方法,查找是否有重载方法,有则调用,并将方法储存在map集合中,以便下一次直接调用

    这样管理以后,首先,不存在传输的对象需要序列号的问题;其次,行为完全是开发者自定义的,可以回溯;再者可以对其进行扩展(比如加入严格模式类型不对不调用响应方法之类的)

    最后来放出我的使用示例


    按钮发生事件.png

    两个按钮分别发送申请事件和同意事件


    单事件.png

    注册单事件


    多事件重载5.png

    注册多事件,并重载了Interger参数的响应体


    发送消息.gif

    可以看到,注册了单事件的界面接收不到同意行为,而多事件可以
    并且注册了多事件行为的界面本身没有Interger类型的响应体,只是重载了它,一样能成功收到

    以上就是简易的通信框架了,如果好用的话,会继续优化

    相关文章

      网友评论

        本文标题:简易App内部消息通信

        本文链接:https://www.haomeiwen.com/subject/nckeuftx.html