okhttp 中是自帶websocket 服務的,網上的教程也很是多。可是不少都沒有註明關鍵一步,須要引入 'com.squareup.okhttp3:okhttp-ws:3.4.2' 才能夠調用webscoket 對象,web
先定義一個靜態的全局okhttp對象,方便之後調用json
public static OkHttpClient okHttpClient;
public static WebSocket webSocket = null;
public static MessageCallBack messageCallBack;
public static synchronized void InstancesOkhttp() { if (okHttpClient == null) { okHttpClient = new OkHttpClient().newBuilder(). readTimeout(3000, TimeUnit.SECONDS)//設置讀取超時時間 .writeTimeout(3000, TimeUnit.SECONDS)//設置寫的超時時間 .connectTimeout(3000, TimeUnit.SECONDS)//設置鏈接超時時間 .build(); if (webSocket == null) { initWebsocket(); } } }
接着實例化websocket,websocket
public static void initWebsocket() { String url = "ws://你的地址"; final Request request = new Request.Builder() .url(url).build(); WebSocketCall webSocketCall = WebSocketCall.create(okHttpClient, request); webSocketCall.enqueue(new WebSocketListener() { @Override public void onOpen(WebSocket webSocket, Response response) { HttpCenter.webSocket = webSocket; } @Override public void onFailure(IOException e, Response response) { } @Override public void onMessage(ResponseBody message) throws IOException { String msg = message.string(); if (messageCallBack == null) { //// TODO: 17/5/20 } else { messageCallBack.onMessage(msg); } } @Override public void onPong(Buffer payload) { } @Override public void onClose(int code, String reason) { System.out.println("MESSAGE: onClose" + code); initWebsocket(); } }); }
很簡單。socket
以後須要統一一個發送方法,同時定義一個用於頁面的回調接口ide
public void setCallBack(MessageCallBack callBack) { this.messageCallBack = callBack; } public void send(String str) { final String m = str; Runnable runnable = new Runnable() { @Override public void run() { try { if (HttpCenter.webSocket != null) HttpCenter.webSocket.sendMessage(RequestBody.create(TEXT, m)); } catch (IOException e) { e.printStackTrace(); } } }; mExecutor.execute(runnable); }
以上基本的封裝結束。佈局
接下來統一消息處理。ui
public class MessageCenter { private MessageCallBack MyMessage; private WebSocket socket; private CommandCenter commandCenter; private HttpCenter httpCenter; public MessageCenter(MessageCallBack messageCenter) { httpCenter = new HttpCenter(); this.MyMessage = messageCenter; httpCenter.setCallBack(messageCenter); commandCenter = new CommandCenter(); } public CommandCenter ChooseCommand() { if (commandCenter != null) return commandCenter; else { commandCenter = new CommandCenter(); return commandCenter; } } public void SendYouMessage(String str) { Log.i("發送了", str); if (HttpCenter.webSocket != null) { socket = HttpCenter.webSocket; } else { HttpCenter.initWebsocket(); } httpCenter.send(str); } public void setCallBackInterFace(MessageCallBack messageCenter) { setHttpCallBack(messageCenter); } private void setHttpCallBack(MessageCallBack messageCenter) { this.MyMessage = messageCenter; httpCenter.setCallBack(this.MyMessage); } }
思路很簡單 ,this
接着根據業務需求定義一個請求類來統一發送接口,url
private JSONObject jsonObj; private JSONObject jsonObjArr; ///////////////////////////////////// private JSONObject addData(JSONObject ob, String name, Object vlaue) { try { ob.put(name, vlaue); } catch (JSONException e) { e.printStackTrace(); } return ob; } private JSONObject addCmd(JSONObject cmd, String cmdName, JSONObject data) { try { cmd.put("cmd", cmdName); cmd.put("data", data); } catch (JSONException e) { e.printStackTrace(); } return cmd; }
封裝部分結束,spa
接下來調用,由於會有大量重複性的代碼,因此先定義一個Activity的基類
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //設置佈局內容 setContentView(getLayoutId()); //綁定butterkife setButterKnife(); //初始化控件 initViews(savedInstanceState); } public abstract void setButterKnife(); public abstract int getLayoutId(); protected abstract void initViews(Bundle savedInstanceState); protected void DealMessageForMe(String s, Observer observer){ Observable.just(s) .observeOn(AndroidSchedulers .mainThread()) .subscribe(observer); } }
結合Gson 和Observer來解析和處理數據
observer = new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
JSONObject cmd = JSONUtils.StringToJSON(s);
if (JSONUtils.getString(cmd, "cmd").equals("xxx")) {
swipe.setRefreshing(false);
Gson gson = new Gson();
Type type = new TypeToken<WorkBean>() {
}.getType();
workBean = gson.fromJson(String.valueOf(cmd), type);
listdata.clear();
listdata.addAll(workBean.getData());
adapter.notifyDataSetChanged();
}
}
};
PS: 由於接口被聲明爲靜態,因此會出現數據請求混亂的狀況,這是須要在onResume這指定當前的回調接口
messageCenter.setCallBackInterFace(this);