1. 程式人生 > >WebSocket安卓客戶端實現詳解(三)–服務端主動通知

WebSocket安卓客戶端實現詳解(三)–服務端主動通知

this override 連接 繼續 true www. 格式 代碼 ati

  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 {
  
[email protected]

/* */
  
  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);
  
  }
  
  //標記註解
  
[email protected](ElementType.TYPE)
  
[email protected](RetentionPolicy.RUNTIME)
  
[email protected]
  
  public @interface NotifyClass {
  
  Class<?> value();
  
  }
  
  //具體邏輯對應的處理子類
  
[email protected](AnnounceMsgNotify.class)
  
  public class AnnounceMsgListener implements INotifyListener<AnnounceMsgNotify> {
  
[email protected]
  
  public void fire(AnnounceMsgNotify www.wmyl110.com announceMsgNotify) {
  
  //這裏處理具體的邏輯
  
  }
  
  }
  
  //對應數據bean
  
  public class AnnounceMsgNotify {
  
[email protected]("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安卓客戶端實現詳解(三)–服務端主動通知