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. CF809D Hitchhiking in the Baltic States LIS、平衡树

    传送门 看到最长上升子序列肯定是DP 设\(f_i\)表示计算到当前,长度为\(i\)的最长上升子序列的最后一项的最小值,显然\(f_i\)是一个单调递增的序列. 转移:对于当前计算的元素\(x\), ...

  2. Ionic下的Jpush消息推送与内容显示

    本文测试Jpush将消息推送给手机端,手机端点击通知栏,即可看到具体的推送内容. 1.极光推送消息设置 设置附加字段: 点击发送,手机端收到消息通知. 2.手机接收到的消息通知 点击之后进入具体的页面 ...

  3. python中和生成器协程相关yield from之最详最强解释,一看就懂(二)

    一. 从列表中yield  语法形式:yield from <可迭代的对象实例> python中的列表是可迭代的, 如果想构造一个生成器逐一产生list中元素,按之前的yield语法,是在 ...

  4. svg矢量图在flex布局中样式扭曲的问题

    问题机型 小米5 华为nova 其他未知的可能机型 问题描述 利用flex 布局的一行中, 左一样式: -webkit-box-flex: 0; flex: 0 1 auto; 左二样式: -webk ...

  5. html5制作导航条

    (1)background-repeat:no-repeat;图片不平铺 (2)使用<ul>和<li>便签,代码简介有序.易于编排. (3)在引入外部css文件时,<li ...

  6. Sprint 冲刺第三阶段第3-5天 数据库代码

    数据库代码: package com.example.brdemo; import android.app.Activity; import android.content.Intent; impor ...

  7. iOS开发线程安全问题

    先来看一下代码: - (void)viewDidLoad { [super viewDidLoad]; self.testStr = @"String initial complete&qu ...

  8. 软件工程(GZSD2015) 第二次作业进度

    贵州师范大学软件工程第二次作业 徐 镇 王铭霞 张 英 涂江枫 张 燕 安 坤 周 娟 杨明颢 杨家堂 罗文豪 娄秀盛 周 娟 李盼 岳庆 张颖 李丽思 邓婷 唐洁 郑倩 尚清丽 陈小丽 毛茸 宋光能 ...

  9. Jfrog Maven jenkins pipeline 流水线 培训 简单实验

    1. 公司购买了一套jfrog artifactory ,然后厂商组织了一次培训 本次简单记录一下 jenkins和jfrog 二进制仓库的简单连接使用 2. 前期环境准备. scp jdk的tar包 ...

  10. Linux常用指令-ssh

    目录 ssh远程登陆 ssh免密码登陆 生成公钥和私钥 将公钥复制到其他从机 文件说明 id_rsa id_rsa.pub authorized_keys known_host SSH(远程连接工具) ...