okhttp 中是自带websocket 服务的,网上的教程也非常多。但是很多都没有注明关键一步,需要引入 'com.squareup.okhttp3:okhttp-ws:3.4.2' 才可以调用webscoket 对象,
先定义一个静态的全局okhttp对象,方便以后调用
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,
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(); } }); }
很简单。
之后需要统一一个发送方法,同时定义一个用于页面的回调接口
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); }
以上基本的封装结束。
接下来统一消息处理。
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); } }
思路很简单 ,
接着根据业务需求定义一个请求类来统一发送接口,
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; }
封装部分结束,
接下来调用,因为会有大量重复性的代码,所以先定义一个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() {
@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() {
}.getType();
workBean = gson.fromJson(String.valueOf(cmd), type);
listdata.clear();
listdata.addAll(workBean.getData());
adapter.notifyDataSetChanged();
}
}
};
PS: 因为接口被声明为静态,所以会出现数据请求混乱的情况,这是需要在onResume这指定当前的回调接口
messageCenter.setCallBackInterFace(this);