WebSocket安卓客户端实现详解(三)–服务端主动通知
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安卓客户端实现详解(三)–服务端主动通知的更多相关文章
- WebSocket安卓客户端实现详解(一)–连接建立与重连
http://blog.csdn.net/zly921112/article/details/72973054 前言 这里特别说明下因为WebSocket服务端是公司线上项目所以这里url和具体协议我 ...
- 开源PLM软件Aras详解三 服务端简易开发
废话少说,直接进入主题, 以CAD为例: 先找到CAD对象类:具体操作见下图 双击打开,找到服务端事件:见下图 点击新建对象,点击添加,新建Method 编写Method,语言分为前端和后端,前端支持 ...
- Zabbix配置文件详解之服务端zabbix_server
zabbix作为运维邻域不可缺少的一员,它的各种文档可是数不胜数啊,但是关于配置文件的解释与说明就有点少.这里列出zabbix配置文件篇之zabbix_server. Zabbix Server端配置 ...
- 详解----memcache服务端与客户端
Memcache是danga.com的一个项目,用这个缓存项目来构建自己大负载的网站,来分担数据库的压力. 它可以应对任意多个连接,使用非阻塞的网络IO.由于它的工作机制是在内存中开辟一块空间,然后建 ...
- Mir2源码详解之服务端-登录网关(LoginGate)
传奇这款游戏,一直对我的影响很大.当年为了玩传奇,逃课,被老师叫过N次家长.言归正传,网上有很多源码,当然了,都是delphi的.并且很多源码还不全, 由于一直学习的c.c++.delphi还真不懂. ...
- Mir2源码详解之服务端-选择(角色)网关(SelGate)
其实,SelGate也就是 LoginGate,其源码实现完全相同.不必怀疑,市面上的都是这么做~!这里单独写这篇文章,就是为了说明这点!
- K2 K2Blackpearl安装步骤详解(服务端)
转:http://www.cnblogs.com/dannyli/archive/2011/11/30/2269485.html 以下是K2 Blackpearl的安装步骤,本人亲测可用哦. 1.安装 ...
- 安卓集成发布详解(二)gradle
转自:http://frank-zhu.github.io/android/2015/06/15/android-release_app_build_gradle/ 安卓集成发布详解(二) 15 Ju ...
- Android 之窗口小部件详解(三) 部分转载
原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...
随机推荐
- Luogu4528 CTSC2008 图腾 树状数组、容斥
传送门 设$f_i$表示$i$排列的数量,其中$x$表示不确定 那么$$ans=f_{1324}-f_{1432}-f_{1243}=(f_{1x2x}-f_{1423})-(f_{14xx}-f_{ ...
- JS-JS创建数组的三种方法
隐式创建 var arr=["Audi","BMW","Volvo"]; 直接实例化 var arr=new Array("Aud ...
- 汇编 指令lodsb,lodsw,lodsd
知识点: 汇编指令 lodsb,lodsw,lodsd 一.汇编指令LODSB //scasb scasw scasd //stosb stosw stosd 1. __asm lodsb //作用 ...
- Hogp连接流程分析
当BLE设备已经完成配对,并且完成GATT服务的搜索,下一步就开始profile 的连接流程了,一般LE设备都是走的HOGP的流程,我们这篇文章就分析一下hogp的连接流程. 连接是从framewor ...
- 详解javascript中this的工作原理
在 JavaScript 中 this 常常指向方法调用的对象,但有些时候并不是这样的,本文将详细解读在不同的情况下 this 的指向. 一.指向 window: 在全局中使用 this,它将会指向全 ...
- Quartz_配置
quartz_jobs.xml job 任务 其实就是1.x版本中的<job-detail>,这个节点是用来定义每个具体的任务的,多个任务请创建多个job节点即可 name(必填) 任务名 ...
- yum源使用的几个报错小总结 (例如: python2.6.6 下yum不能使用: No module named yum)
服务器上的yum突然不好使用,使用yum时有如下几个保持,解决方案如下: 1)Error: Cannot retrieve repository metadata (repomd.xml) for r ...
- MySQL两种存储引擎: MyISAM和InnoDB 简单总结
MyISAM是MySQL的默认数据库引擎(5.5版之前),由早期的ISAM(Indexed Sequential Access Method:有索引的顺序访问方法)所改良.虽然性能极佳,但却有一个缺点 ...
- Python进阶量化交易场外篇5——标记A股市场涨跌周期
新年伊始,很荣幸笔者的<教你用 Python 进阶量化交易>专栏在慕课专栏板块上线了,欢迎大家订阅!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外会陆续推出一些手记来辅助同学们学习 ...
- Python-dict-12
字典 Why:咱们目前已经学习到的容器型数据类型只有list,那么list够用?他有什么缺点呢? 1. 列表可以存储大量的数据类型,但是如果数据量大的话,他的查询速度比较慢. 2. 列表只能按照顺序存 ...