频道栏目
首页 > 资讯 > 其他综合 > 正文

WebSocket安卓客户端实现详解(三)–服务端主动通知

17-08-09        来源:[db:作者]  
收藏   我要投稿

服务端主动通知


热身完毕,我们先回顾下第一篇中讲到的服务端主动通知的流程

  1. 根据notify中事件类型找到对应的处理类,处理对应逻辑.

  2. 然后用eventbus通知对应的ui界面更新.

  3. 如果需要ack,发送ack请求.

    在回顾下第二篇中服务端主动通知协议的格式

    {
        "resp_event": 20,
        "action": "",
        "seq_id": 11111111,
        "resp": {
    
          }
        }
    }我们根据resp_event为20判断这次响应是服务端主动通知,然后通过action找到对应处理类,然后把resp中数据解析成对应的bean传入对应处理类执行对应业务逻辑.

    show code

    public class WsManager {
    
      ....跟之前相同代码省略.....
    
      class WsListener extends WebSocketAdapter {
          @Override
          public void onTextMessage(WebSocket websocket, String text) throws Exception {
              super.onTextMessage(websocket, text);
              Logger.t(TAG).d("receiverMsg:%s", text);
    
              Response response = Codec.decoder(text);//解析出第一层bean
              if (response.getRespEvent() == 10) {//响应
                  CallbackWrapper wrapper = callbacks.remove(
                          Long.parseLong(response.getSeqId()));//找到对应callback
                  if (wrapper == null) {
                      Logger.t(TAG).d("(action:%s) not found callback", response.getAction());
                      return;
                  }
    
                  try {
                      wrapper.getTimeoutTask().cancel(true);//取消超时任务
                      ChildResponse childResponse = Codec.decoderChildResp(
                              response.getResp());//解析第二层bean
                      if (childResponse.isOK()) {
    
                          Object o = new Gson().fromJson(childResponse.getData(),
                                  wrapper.getAction().getRespClazz());
    
                          wrapper.getTempCallback().onSuccess(o);
                      } else {
                          wrapper.getTempCallback()
                                  .onError(ErrorCode.BUSINESS_EXCEPTION.getMsg(), wrapper.getRequest(),
                                          wrapper.getAction());
                      }
                  } catch (JsonSyntaxException e) {
                      e.printStackTrace();
                      wrapper.getTempCallback()
                              .onError(ErrorCode.PARSE_EXCEPTION.getMsg(), wrapper.getRequest(),
                                      wrapper.getAction());
                  }
    
              } else if (response.getRespEvent() == 20) {//通知
                  NotifyListenerManager.getInstance().fire(response);
              }
          }
    
      }
    
      ....跟之前相同代码省略.....
    
    }

    我们先解析出第一层bean然后根据resp_event为20执行NotifyListenerManager通知管理类对外暴露的fire()方法.

    public class NotifyListenerManager {
        private final String TAG = this.getClass().getSimpleName();
        private volatile static NotifyListenerManager manager;
        private Map map = new HashMap<>();
    
        private NotifyListenerManager() {
            regist();
        }
    
        public static NotifyListenerManager getInstance() {
            if (manager == null) {
                synchronized (NotifyListenerManager.class) {
                    if (manager == null) {
                        manager = new NotifyListenerManager();
                    }
                }
            }
            return manager;
        }
    
        private void regist() {
            map.put("notifyAnnounceMsg", new AnnounceMsgListener());
        }
    
        public void fire(Response response) {
            String action = response.getAction();
            String resp = response.getResp();
            INotifyListener listener = map.get(action);
            if (listener == null) {
                Logger.t(TAG).d("no found notify listener");
                return;
            }
    
            NotifyClass notifyClass = listener.getClass().getAnnotation(NotifyClass.class);
            Class clazz = notifyClass.value();
            Object result = null;
            try {
                result = new Gson().fromJson(resp, clazz);
            } catch (JsonSyntaxException e) {
                e.printStackTrace();
            }
            Logger.t(TAG).d(result);
            listener.fire(result);
        }
    
    
    }

    NotifyListenerManager是一个单例的类,在第一次创建的时候在构造方法中执行了regist方法,这是一个变种的观察者模式对于添加观察者这个过程我们直接在regist方法中写好了,如果增加了新的业务逻辑我们只需要在regist方法中put新添加的action与对应处理类.对外暴露的fire方法根据传入的responsse中action找到对应的处理类,拿到处理类对应的注解标记的class,将服务端返回的resp解析成对应的bean丢到对应处理类执行对应逻辑.

    //抽象接口
    public interface INotifyListener {
        void fire(T t);
    }
    
    //标记注解
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface NotifyClass {
    
        Class value();
    
    }
    
    //具体逻辑对应的处理子类
    @NotifyClass(AnnounceMsgNotify.class)
    public class AnnounceMsgListener implements INotifyListener {
    
        @Override
        public void fire(AnnounceMsgNotify announceMsgNotify) {
            //这里处理具体的逻辑
        }
    }
    
    //对应数据bean
    public class AnnounceMsgNotify {
        @SerializedName("msg_version")
        private String msgVersion;
    
        public String getMsgVersion() {
            return msgVersion;
        }
    
        public void setMsgVersion(String msgVersion) {
            this.msgVersion = msgVersion;
        }
    
    }

    如果新增业务逻辑我们只需要实现新的业务逻辑类,然后在NotifyListenerManager的regist方法中put新增的action与listener映射关系,对外只需要调用NotifyListenerManager.getInstance().fire(response)即可,实现了解耦.

    到此websocket介绍完啦….鼓掌鼓掌鼓掌.

相关TAG标签
上一篇:微信开发中的消息验证与消息回复
下一篇:RocketMQ存储篇——HA高可用
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站