WebSocket安卓客户端实现详解(三)–服务端主动通知
  
  本篇依旧是接着上一篇继续扩展,还没看过之前博客的小伙伴,这里附上前几篇地址
  
  WebSocket安卓客户端实现详解(一)–连接建立与重连
  
  WebSocket安卓客户端实现详解(二)–客户端发送请求
  
  终于是最后一篇啦,有点激动\ ( ≧▽≦ ) /啦啦啦,
  
  服务端主动通知
  
  热身完毕,我们先回顾下第一篇中讲到的服务端主动通知的流程
  
  根据notify中事件类型找到对应的处理类,处理对应逻辑.
  
  然后用eventbus通知对应的ui界面更新.
  
  如果需要ack,发送ack请求.
  
  在回顾下第二篇中服务端主动通知协议的格式
  
  {
  
  "resp_event": 20,
  
  "action": "",
  
  "seq_id": 11111111,
  
  我们根据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 = www.wmyl166.cn callbacks.remove(
  
  Long.parseLong(response.getSeqId()));//找到对应callback
  
  if (wrapper == null) {
  
  Logger.t(TAG).d("(action:%s) not found www.xingchexiu.com 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( www.chuangyed.com response);

  我们先解析出第一层bean然后根据resp_event为20执行NotifyListenerManager通知管理类对外暴露的fire()方法.
  
  public class NotifyListenerManager {
  
  private final String TAG = this.getClass().getSimpleName();
  
  private volatile static NotifyListenerManager manager;
  
  private Map<String, INotifyListener> 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<T> {
  
  void fire(T t);
  
  }
  
  //标记注解
  
  @Target(ElementType.TYPE)
  
  @Retention(RetentionPolicy.RUNTIME)
  
  @Documented
  
  public @interface NotifyClass {
  
  Class<?> value();
  
  }
  
  //具体逻辑对应的处理子类
  
  @NotifyClass(AnnounceMsgNotify.class)
  
  public class AnnounceMsgListener implements INotifyListener<AnnounceMsgNotify> {
  
  @Override
  
  public void fire(AnnounceMsgNotify www.wmyl110.com 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的www.wmyl119.cn regist方法中put新增的action与listener映射关系,对外只需要调用NotifyListenerManager.getInstance().fire(response)即可,实现了解耦.
  
  到此websocket介绍完啦….鼓掌鼓掌鼓掌.
  
  总结
  
  对于websocket使用我已经尽我所能最详细的讲解了一遍,但是也避免不了有所疏漏和错误还望各位小伙伴指出.
  
  然后虽然写了三篇但是还有几个点说的不够详细,这里我一一列举感兴趣的小伙伴可以自己看看.
  
  获取连接地址与选择连接地址的策略
  
  重连的策略
  
  心跳的策略
  
  进程保活
  
  最后感谢各位小伙伴捧场能把三篇都看完的绝对是真爱啊…

WebSocket安卓客户端实现详解(三)–服务端主动通知的更多相关文章

  1. WebSocket安卓客户端实现详解(一)–连接建立与重连

    http://blog.csdn.net/zly921112/article/details/72973054 前言 这里特别说明下因为WebSocket服务端是公司线上项目所以这里url和具体协议我 ...

  2. 开源PLM软件Aras详解三 服务端简易开发

    废话少说,直接进入主题, 以CAD为例: 先找到CAD对象类:具体操作见下图 双击打开,找到服务端事件:见下图 点击新建对象,点击添加,新建Method 编写Method,语言分为前端和后端,前端支持 ...

  3. Zabbix配置文件详解之服务端zabbix_server

    zabbix作为运维邻域不可缺少的一员,它的各种文档可是数不胜数啊,但是关于配置文件的解释与说明就有点少.这里列出zabbix配置文件篇之zabbix_server. Zabbix Server端配置 ...

  4. 详解----memcache服务端与客户端

    Memcache是danga.com的一个项目,用这个缓存项目来构建自己大负载的网站,来分担数据库的压力. 它可以应对任意多个连接,使用非阻塞的网络IO.由于它的工作机制是在内存中开辟一块空间,然后建 ...

  5. Mir2源码详解之服务端-登录网关(LoginGate)

    传奇这款游戏,一直对我的影响很大.当年为了玩传奇,逃课,被老师叫过N次家长.言归正传,网上有很多源码,当然了,都是delphi的.并且很多源码还不全, 由于一直学习的c.c++.delphi还真不懂. ...

  6. Mir2源码详解之服务端-选择(角色)网关(SelGate)

    其实,SelGate也就是 LoginGate,其源码实现完全相同.不必怀疑,市面上的都是这么做~!这里单独写这篇文章,就是为了说明这点!

  7. K2 K2Blackpearl安装步骤详解(服务端)

    转:http://www.cnblogs.com/dannyli/archive/2011/11/30/2269485.html 以下是K2 Blackpearl的安装步骤,本人亲测可用哦. 1.安装 ...

  8. 安卓集成发布详解(二)gradle

    转自:http://frank-zhu.github.io/android/2015/06/15/android-release_app_build_gradle/ 安卓集成发布详解(二) 15 Ju ...

  9. Android 之窗口小部件详解(三)  部分转载

    原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...

随机推荐

  1. Linux shell ftp命令下载文件 根据文件日期

    需求:ftp获取远程数据的文件,根据文件的创建时间点下载文件. 可以自行扩展根据文件的大小等其他需求. 知识点总结: 1.获取文件的时间: ls -lrt|awk '{print $6" & ...

  2. UVA1265 Tour Belt Kruskal重构树、倍增、树上差分

    题目传送门 题意:定义$Tour \, Belt$为某张图上的一个满足以下条件的点集:①点集中至少有$2$个点②任意两点互相连通③图上两个端点都在这个点集中的边的权值的最小值严格大于图上只有一个端点在 ...

  3. Ionic2 调用Custom Cordova Plugin方法

    APP升级到Ionic2之后,如何调用自己写的pulgin,一直测试不成功,现记录这一经过. plugin目前可以分为3类,A类是ionic-native自带的,可以直接导入Typescript类,直 ...

  4. 随机森林和GBDT的几个核心问题

    随机森林random forest的pro和con是什么?优势是accuracy高,但缺点是速度会降低,并且解释性interpretability会差很多,也会有overfitting的现象. 为什么 ...

  5. subprocess.Popen指令包含中文导致乱码问题解决

    其实解决起来非常简单,如果了解到Windows中文系统编码为GB2312的话 只需将你包含中文的指令字符串编码为GB2312即可 cmd = u'cd 我的文档' cmd.encode('gb2312 ...

  6. JSP页面<%@ ...%>是什么意思?

    这表示是指令,主要用来提供整个JSP 网页相关的信息,并且用来设定JSP网页的相关属性,例如:网页的编码方式.语法.信息等.起始符号为: <%@终止符号为: %>目前有三种指令:page. ...

  7. Mysql8.0的登录大坑……(忘记登录密码也可以这么搞)

    关于安装和使用就不说了,属于基本操作了: 我来重点记录一下关于使用前,使用navicat登录的时候报错,1130和2059 查看安装后随机生成的密码: grep 'temporary password ...

  8. Ubuntu16.04下使用rdesktop命令远程连接windows机器

    前段时间在本机安装了ubuntu16.04桌面版,后来需要远程连接一台win10系统的跳转机,下面介绍使用rdesktop命令远程连接windows机器的操作记录:1)首先安装rdesktop工具 k ...

  9. final个人阅读作业

    一.软件工程M1/M2总结 1.M1阶段总结: 我们团队的软件工程开发是按照前后端来分别开发的,我是负责后端的.我们的项目是做一个北航的社团平台,是一个网站.在后端我们使用的是ruby on rail ...

  10. 【CV】ICCV2015_Learning Temporal Embeddings for Complex Video Analysis

    Learning Temporal Embeddings for Complex Video Analysis Note here: it's a review note on novel work ...