现在Android网络方面的第三方库很多,volley,Retrofit,OKHttp等,各有各自的特点。okhttp是一款高效的HTTP客户端,支持连接同一地址的链接共享同一个socket,通过连接池来减小响应延迟,还有透明的GZIP压缩,请求缓存等优势 。
okhttp官网
github: https://github.com/square/okhttp
一、 使用教程
使用之前,先在在app module build.gradle配置:
compile 'com.google.code.gson:gson:2.2.4'
1. Http Get请求
Request request = new Request.Builder().url("https://www.baidu.com").build(); OkHttpClient client = new OkHttpClient(); Call call = client.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } /** * 此时还在非UI线程中 * @param call * @param response * @throws IOException */ @Override public void onResponse(Call call, Response response) throws IOException { } });2. Http Post请求
OkHttpClient client = new OkHttpClient(); FormBody.Builder builder = new FormBody.Builder(); builder.add("mb", "19811230100").add("pwd", "999999q"); Request request = new Request.Builder().url("").post(builder.build()).build(); Call call = client.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { } /** * 此时还在非UI线程中 * @param call * @param response * @throws IOException */ @Override public void onResponse(Call call, Response response) throws IOException { } });
二、封装
OKHttpException.java
package com.jackie.sample.okhttp.exception; /** * Created by Administrator on 2016/10/30. */ public class OkHttpException extends Exception { private static final long serialVersionUID = 1L; /** * the server return code */ private int ecode; /** * the server return error message */ private Object emsg; public OkHttpException(int ecode, Object emsg) { this.ecode = ecode; this.emsg = emsg; } public Object getEmsg() { return emsg; } public void setEmsg(Object emsg) { this.emsg = emsg; } public int getEcode() { return ecode; } public void setEcode(int ecode) { this.ecode = ecode; } }DisposeDataHandler.java
package com.jackie.sample.okhttp.listener; /** * Created by Administrator on 2016/10/30. */ public class DisposeDataHandler { public DisposeDataListener mListener = null; public Class<?> mClazz = null; public DisposeDataHandler(DisposeDataListener listener) { mListener = listener; } public DisposeDataHandler(DisposeDataListener listener, Class<?> clazz) { mListener = listener; mClazz = clazz; } }DisposeDataListener.java
package com.jackie.sample.okhttp.listener; /** * Created by Administrator on 2016/10/30. */ public interface DisposeDataListener { void onSuccess(Object response); void onFailure(Object error); }CommonRequest.java
package com.jackie.sample.okhttp.request; import java.io.File; import java.util.Map; import okhttp3.FormBody; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.Request; import okhttp3.RequestBody; /** * Created by Administrator on 2016/10/30. * 负责创建各种类型的请求对象,包括get,post,文件上传类型,文件下载类型 */ public class CommonRequest { /** * append the params to the url */ public static Request createGetRequest(String url, RequestParams params) { StringBuilder urlBuilder = new StringBuilder(url).append("?"); if (params != null) { for (Map.Entry<String, String> entry : params.urlParams.entrySet()) { urlBuilder.append(entry.getKey()).append("=").append(entry.getValue()).append("&"); } } return new Request.Builder().url(urlBuilder.substring(0, urlBuilder.length() - 1)).get().build(); } /** * create the key-value Request * @param url * @param params * @return */ public static Request createPostRequest(String url, RequestParams params) { FormBody.Builder builder = new FormBody.Builder(); if (params != null) { for (Map.Entry<String, String> entry : params.urlParams.entrySet()) { builder.add(entry.getKey(), entry.getValue()); } } FormBody body = builder.build(); return new Request.Builder().url(url).post(body).build(); } /** * 文件上传请求 */ private static final MediaType FILE_TYPE = MediaType.parse("application/octet-stream"); public static Request createMultiPostRequest(String url, RequestParams params) { MultipartBody.Builder builder = new MultipartBody.Builder(); builder.setType(MultipartBody.FORM); if (params != null) { for (Map.Entry<String, Object> entry : params.fileParams.entrySet()) { if (entry.getValue() instanceof File) { builder.addPart(MultipartBody.Part.createFormData(entry.getKey(), null, RequestBody.create(FILE_TYPE, (File) entry.getValue()))); } else { builder.addFormDataPart(entry.getKey(), String.valueOf(entry.getValue())); } } } return new Request.Builder().url(url).post(builder.build()).build(); } }RequestParams.java
package com.jackie.sample.okhttp.request; import java.io.File; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Created by Administrator on 2016/10/30. */ public class RequestParams { public ConcurrentHashMap<String, String> urlParams = new ConcurrentHashMap<>(); public ConcurrentHashMap<String, Object> fileParams = new ConcurrentHashMap<>(); /** * Constructs a new empty { @code RequestParams } instance. */ public RequestParams() { this((Map<String, String>) null); } /** * Constructs a new RequestParams instance containing the key/value string * params from this specified map. * * @param source * the source key/value string map to add. */ public RequestParams(Map<String, String> source) { if (source != null) { for (Map.Entry<String, String> entry : source.entrySet()) { put(entry.getKey(), entry.getValue()); } } } public void put(String key, String value) { urlParams.put(key, value); } public void put(String key, File file) { fileParams.put(key, file); } }CommonJsonCallback.java
package com.jackie.sample.okhttp.response; import android.os.Handler; import android.os.Looper; import android.text.TextUtils; import com.google.gson.Gson; import com.jackie.sample.okhttp.exception.OkHttpException; import com.jackie.sample.okhttp.listener.DisposeDataHandler; import com.jackie.sample.okhttp.listener.DisposeDataListener; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import okhttp3.Call; import okhttp3.Callback; import okhttp3.Response; /** * Created by Administrator on 2016/10/30. */ /** * 专门处理Json的回调 */ public class CommonJsonCallback implements Callback { /** * the logic layer exception, may alter in different app */ protected final String RESULT_CODE = "ecode"; //有返回则对于http请求来说是成功的,但还有可能失败 protected final int RESULT_CODE_VALUE = 0; protected final String ERROR_MSG = "emsg"; protected final String EMPTY_MSG = ""; /** * the java layer exception, do not same to the logic error */ protected final int NETWORK_ERROR = -1; //the network relative error protected final int JSON_ERROR = -2; //the json relative error protected final int OTHER_ERROR = -3; //the unknown error private DisposeDataListener mListener; private Class<?> mClazz; private Handler mHandler; public CommonJsonCallback(DisposeDataHandler handler) { mListener = handler.mListener; mClazz = handler.mClazz; mHandler = new Handler(Looper.getMainLooper()); } @Override public void onFailure(Call call, final IOException e) { mHandler.post(new Runnable() { @Override public void run() { if (mListener != null) { mListener.onFailure(e); } } }); } @Override public void onResponse(Call call, Response response) throws IOException { //还在子线程中 final String result = response.body().toString(); mHandler.post(new Runnable() { @Override public void run() { handleResponse(result); } }); } private void handleResponse(String result) { if (TextUtils.isEmpty(result)) { if (mListener != null) { mListener.onFailure(new OkHttpException(NETWORK_ERROR, EMPTY_MSG)); return; } } try { JSONObject resultJsonObject = new JSONObject(result); if (resultJsonObject.has(RESULT_CODE)) { if (resultJsonObject.optInt(RESULT_CODE) == RESULT_CODE_VALUE) { if (mClazz == null) { if (mListener != null) { mListener.onSuccess(resultJsonObject); } } else { Gson gson = new Gson(); Object resultObject = gson.fromJson(result, mClazz); if (resultObject == null) { if (mListener != null) { mListener.onFailure(new OkHttpException(JSON_ERROR, EMPTY_MSG)); } } else { //相应真正正确的处理,并且直接返回了实体对象 if (mListener != null) { mListener.onSuccess(resultObject); } } } } } else { if (mListener != null) { mListener.onFailure(new OkHttpException(NETWORK_ERROR, EMPTY_MSG)); } } } catch (JSONException e) { if (mListener != null) { mListener.onFailure(new OkHttpException(OTHER_ERROR, e.getMessage())); } } } }CommonOkHttpClient.java
package com.jackie.sample.okhttp; /** * Created by Administrator on 2016/10/30. */ import com.jackie.sample.okhttp.listener.DisposeDataHandler; import com.jackie.sample.okhttp.response.CommonJsonCallback; import java.security.NoSuchAlgorithmException; import java.util.concurrent.TimeUnit; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import okhttp3.Call; import okhttp3.OkHttpClient; import okhttp3.Request; /** * 用来发送get,post请求的工具类,包括设置一些请求的公用参数 */ public class CommonOkHttpClient { private static final int TIME_OUT = 30; private static OkHttpClient mOkHttpClient; static { OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder(); //对https的认证 okHttpBuilder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String s, SSLSession sslSession) { return true; } }); try { okHttpBuilder.connectTimeout(TIME_OUT, TimeUnit.SECONDS); okHttpBuilder.readTimeout(TIME_OUT, TimeUnit.SECONDS); okHttpBuilder.writeTimeout(TIME_OUT, TimeUnit.SECONDS); okHttpBuilder.followRedirects(true); SSLContext sslContext = SSLContext.getInstance("TLS"); okHttpBuilder.sslSocketFactory(sslContext.getSocketFactory()); mOkHttpClient = okHttpBuilder.build(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } public static void get(Request request, DisposeDataHandler handler) { Call call = mOkHttpClient.newCall(request); call.enqueue(new CommonJsonCallback(handler)); } public static void post(Request request, DisposeDataHandler handler) { Call call = mOkHttpClient.newCall(request); call.enqueue(new CommonJsonCallback(handler)); } }封装之后代码结构图如下:
Get请求