最近需要用到网络请求,用到了Okhttp这个强大的库,写个小博客来做个笔记 先看一下Okhttp3和之前版本的不同之处。
1.Okhttp3和OkHttp的对比
-
OkHttpClient创建方式不同
例如:
OkHttpClient.Builder okHttpClientBuilder = client.newBuilder();
/* 超时设置 */
okHttpClientBuilder.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS);
OkHttpClient mOkHttpClient = okHttpClientBuilder.build();
okhttp直接newOkHttpClient,而okhttp3中提供了Builder,很好的使用了创建者设计模式 有以下参数:
Dispatcher dispatcher; // 分发
Proxy proxy; // 代理
List<Protocol> protocols;
List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors = new ArrayList<>(); // 拦截器 final List<Interceptor> networkInterceptors = new ArrayList<>(); // 网络拦截器 ProxySelector proxySelector;
CookieJar cookieJar;
Cache cache; // 缓存
InternalCache internalCache;
SocketFactory socketFactory;
SSLSocketFactory sslSocketFactory;
HostnameVerifier hostnameVerifier;
CertificatePinner certificatePinner;
Authenticator proxyAuthenticator; // 代理证书
Authenticator authenticator; // 证书
ConnectionPool connectionPool;
Dns dns; // DNS
boolean followSslRedirects;
boolean followRedirects;
boolean retryOnConnectionFailure;
int connectTimeout;
int readTimeout;
int writeTimeout;
-
cookie的设置方式不同:
okhttp调用OkHttpClient的setCookieHandler方法,CookieHandler是Android SDK提供的标注的cookie管理,CookieHandler 的之类CookieManager实现了cookie的具体管理方法,构建CookieManager需要实现CookieStore接口,系统提供了一个默认的实现CookieStoreImpl,只负责把cookie存储在内存中。
-
post消息体构建方式不同
okhttp使用MultipartBuilder,FormEncodingBuilder构建post消息体,最终构建出来的都是RequestBody,而okhttp3增加了RequestBody的子类,构造器放到了RequestBody的子类中,MultipartBody.Builder既可以添加表单数据,也可以添加文件等二进制数据
-
Call和Callback不同
okhttp3 之前用CookieHandler管理cookie
/* cookie管理 */
mCookieHandler = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
mOkHttpClient.setCookieHandler(mCookieHandler);
3.0 之后新增了两个类Cookiejar、Cookie两个类,开放接口,需要用户自己去实现cookie的配管理。用户可以直接在CookieJar中简单设置Cookie的管理,如下:
okHttpClientBuilder.cookieJar(new CookieJar() {
private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put(url, cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = cookieStore.get(url);
return cookies != null ? cookies : new ArrayList<Cookie>();
}
});
-
OkHttpClient的Cancel方法去掉
3.0之前我们去掉call 可以直接使用mOkHttpClient.cancel(tag);3.0之后直接阉割掉此方法我们可以采用如下方法:
public void cancelCallsWithTag(Object tag) {
checkInit();
if (tag == null) {
return;
}
synchronized (mOkHttpClient.dispatcher().getClass()) {
for (Call call : mOkHttpClient.dispatcher().queuedCalls()) {
if (tag.equals(call.request().tag())) call.cancel();
}
for (Call call : mOkHttpClient.dispatcher().runningCalls()) {
if (tag.equals(call.request().tag())) call.cancel();
}
}
}
2.Okhttp参数的构造
public class Params {
public static final String METHOD_GET = "get";
public static final String METHOD_POST = "post";
//3个构造参数 一般参数 file head
private HashMap<String, Object> urlParams = new HashMap<>();
private HashMap<String, File> fileParams = new HashMap<>();
private HashMap<String, String> headers = new HashMap<>();
private String api = "";
private String baseUrl = "";
private String method;
public Params() {
urlParams = new HashMap<String, Object>();
fileParams = new HashMap<String, File>();
headers = new HashMap<String, String>();
setBaseUrl(Constants.me().getHost());
//统一添加请求头
headers.put("Accept", "application/json");
headers.put("Version", Constants.me().getVersionName());
headers.put("Gis-Lat", String.valueOf(Constants.me().getLatitude()));
headers.put("Gis-Lng", String.valueOf(Constants.me().getLongitude()));
String token = Constants.me().getToken();
if (!TextUtils.isEmpty(token)) {
headers.put("Authorization", "Bearer " + token);
}
setMethod(METHOD_POST);
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getApi() {
return api;
}
public void setApi(String api) {
this.api = api;
}
public String getUrl() {
return baseUrl + api;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public void put(String key, Object value) {
if (key != null) {
urlParams.put(key, value);
}
}
public void put(String key, String value) {
if (key != null) {
urlParams.put(key, value);
}
}
public void put(String key, int value) {
if (key != null) {
urlParams.put(key, String.valueOf(value));
}
}
public void put(String key, double value) {
if (key != null) {
urlParams.put(key, String.valueOf(value));
}
}
public void put(String key, float value) {
if (key != null) {
urlParams.put(key, String.valueOf(value));
}
}
public void putHeaders(final String key, final int value) {
this.putHeaders(key, String.valueOf(value));
}
public void putHeaders(final String key, final String value) {
headers.put(key, value);
}
/**
* @param key
* @param file
*/
public void put(String key, File file) {
if (file != null && file.exists()) {
fileParams.put(key, file);
}
}
//是否为文件
public boolean isMultipart() {
return !fileParams.isEmpty();
}
public HashMap<String, Object> getUrlParams() {
return urlParams;
}
public HashMap<String, File> getFileParams() {
return fileParams;
}
public HashMap<String, String> getHeaders() {
return headers;
}
@Override
public String toString() {
return urlParams.toString();
}
}
3.Okhttp的封装
final public class HttpKit {
private static final int DEFAULT_MILLISECONDS = 60000; //默认的超时时间
private OkHttpClient.Builder okHttpClientBuilder;
private OkHttpClient okHttpClient;
private Handler mDelivery;
private Context mContext;
private final List<ResponseHandler> handlers = new ArrayList<>();//请求返回值处理
private PersistentCookieStore cookieStore;//永久化保存cookie
public interface HttpCallback<T> {
//开始的时候调用,子类可选择实现
public void onStarted(Request request);
//当进度条改变的时候,子类可选择实现
public void onProgressChanged(float progress, long total);
/**
* response是否正确
*
* @param response
* @return
*/
@Deprecated
public boolean validateReponse(Response response);
//解析数据,可选择实现,一般子类会自定义一个callback类,去解析
public T parseNetworkResponse(Response response) throws ApiException;
//子类回调,可选择实现
public void onError(ApiException e);
//子类回调
public abstract void onResponse(T response);
}
private static final HttpKit me = new HttpKit();
private HttpKit() {
okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.connectTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
okHttpClientBuilder.readTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
okHttpClientBuilder.writeTimeout(DEFAULT_MILLISECONDS, TimeUnit.MILLISECONDS);
mDelivery = new Handler(Looper.getMainLooper());
}
public static HttpKit me() {
return me;
}
//当需要使用cookie的时候,调用
public static HttpKit init(Context context) {
me().setContext(context);
return me();
}
private void setContext(Context context) {
this.mContext = context;
cookieStore = new PersistentCookieStore(mContext);//永久化保存cookie
CookieJarImpl cookieJar = new CookieJarImpl(cookieStore);
okHttpClientBuilder.cookieJar(cookieJar);
}
//设置cookie
public void setCookie(Uri uri, Cookie cookie) {
HttpUrl httpUrl = new HttpUrl.Builder().scheme(uri.getScheme()).host(uri.getHost()).build();
cookieStore.add(httpUrl, cookie);
}
public void removeAllCookie() {
cookieStore.removeAll();
}
//本地拦截器
public HttpKit addInterceptor(Interceptor interceptor) {
okHttpClientBuilder.addInterceptor(interceptor);
return this;
}
//网络拦截器
public HttpKit addNetworkInterceptor(Interceptor interceptor) {
okHttpClientBuilder.addNetworkInterceptor(interceptor);
return this;
}
public List<ResponseHandler> handlers() {
return handlers;
}
public HttpKit addHandler(ResponseHandler handler) {
handlers.add(handler);
return this;
}
public Handler getDelivery() {
return mDelivery;
}
public void build() {
okHttpClient = okHttpClientBuilder.build();
}
private Request buildRequest(Params params) {
Request.Builder builder = new Request.Builder();
builder.url(params.getUrl());
//头
if (!params.getHeaders().isEmpty()) {
for (Map.Entry<String, String> header : params.getHeaders().entrySet()) {
if (header.getKey() != null) {
builder.addHeader(header.getKey(), header.getValue());
}
}
}
//文件表单上传
if (params.isMultipart()) {
MultipartBody.Builder body = new MultipartBody.Builder();
body.setType(MultipartBody.FORM);
//有url
if (!params.getUrlParams().isEmpty()) {
for (Map.Entry<String, Object> param : params.getUrlParams().entrySet()) {
if (param.getKey() != null) {
body.addFormDataPart(param.getKey(), (String) param.getValue());
}
}
}
//有file对象
for (Map.Entry<String, File> param : params.getFileParams().entrySet()) {
File file = param.getValue();
if (file != null && file.exists()) {
RequestBody fileBody = RequestBody.create(MediaType.parse("application/octet-stream"), file);
body.addFormDataPart(param.getKey(), file.getName(), fileBody);
}
}
builder.post(body.build());
//不是表单,是一般的Post请求的话
} else if (Params.METHOD_POST.equals(params.getMethod())) {
FormBody.Builder body = new FormBody.Builder();
body.add("i", CryptKit.encrypt(params.getUrlParams(), params.getUrl()));
builder.post(body.build());
}
return builder.build();
}
//同步请求
public Response execute(Params params) throws IOException {
Request request = buildRequest(params);
Call call = okHttpClient.newCall(request);
return call.execute();
}
/**
* get请求不做parseNetworkResponse处理,原数据返回
*
* @param params
* @param callback
*/
public void get(Params params, final HttpCallback callback) {
Request request = buildRequest(params);
if (callback != null) callback.onStarted(request);
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
sendFail(new ApiException(e), callback);
}
@Override
public void onResponse(Call call, Response response) {
try {
if (call.isCanceled()) {
sendFail(new ApiException("取消", -1), callback);
return;
}
Object o = callback.parseNetworkResponse(response);
sendSuccess(o, callback);
} catch (ApiException e) {
sendFail(e, callback);
} finally {
if (response.body() != null)
response.body().close();
}
}
});
}
public void post(final Params params, final HttpCallback callback) {
if (params == null || callback == null) {
Log4a.e("post params null");
return;
}
Request request = buildRequest(params);
if (callback != null) callback.onStarted(request);
Call call = okHttpClient.newCall(request);
Log4a.e("======>post "+params.getUrl());
Log4a.e("======> params:"+params.toString());
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
sendFail(new ApiException(e.getCause()), callback);
}
@Override
public void onResponse(Call call, Response response) {
try {
if (call.isCanceled()) {
sendFail(new ApiException("取消", -1), callback);
return;
}
Object o = callback.parseNetworkResponse(response);
sendSuccess(o, callback);
} catch (ApiException e) {
sendFail(e, callback);
} finally {
if (response.body() != null)
response.body().close();
}
}
});
}
private void sendFail(final ApiException e, final HttpCallback callback) {
if (callback == null) return;
mDelivery.post(new Runnable() {
@Override
public void run() {
try {
if (callback != null) {
callback.onError(e);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void sendSuccess(final Object object, final HttpCallback callback) {
if (callback == null) return;
mDelivery.post(new Runnable() {
@Override
public void run() {
try {
if (callback != null && object != null) {
callback.onResponse(object);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
4.子类自定义CallBack方法执行相应的操作,例如解析数据等
public abstract class JSONCallback<T> extends TypeToken<T> implements HttpKit.HttpCallback<T> {
private Type mClass;//获取类似List<Student>或者 Student的type
public JSONCallback() {
mClass = getType();
}
public void onStarted(Request request) {
}
public void onProgressChanged(float progress, long total) {
}
/**
* response是否正确
*
* @param response
* @return
*/
@Deprecated
public boolean validateReponse(Response response) {
return true;
}
public T parseNetworkResponse(Response response) throws ApiException {
String resp = "";
String data = "";
int status;
String message;
try {
resp = response.body().string();
Log4a.e("======>> response:"+response.request().url().url());
Log4a.json(resp);
} catch (IOException e) {
throw new ApiException(e);
}
try {
JSONObject jsonObject = new JSONObject(resp);
status = jsonObject.getInt("code");
message = jsonObject.getString("message");
if (status == 1000 && jsonObject.has("data")) {
data = jsonObject.getString("data");
}
} catch (JSONException e) {
throw new ApiException(e);
}
List<ResponseHandler> handlers = HttpKit.me().handlers();
if (handlers != null && handlers.size() > 0) {
for (ResponseHandler handler : handlers)
handler.onHandler(status, message, response.request().url().url().getPath());
}
if (status != 1000) {
throw new ApiException(message, status);
}
try {
if (GsonKit.isSubObjectOf(mClass, List.class)) {
if ("".equals(data) || data == null||"{}".equals(data)) {
data = "[]";
}
} else {
if ("".equals(data) || data == null||"[]".equals(data)) {
data = "{}";
}
}
return GsonKit.fromJson(data, mClass);
} catch (Exception e) {
throw new ApiException(message, status, e);
}
}
public void onError(ApiException e) {
if (e.getStatus() == 0)
ViewKit.shortToast("联网失败,请检查网络");
else if (e.getStatus() == -1) {// TODO: 2016/11/26
} else if (!StringKit.isEmpty(e.getMessage()))
ViewKit.shortToast(e.getMessage());
}
public abstract void onResponse(T response);
}
5.Cookie的一些设置
//当需要使用cookie的时候,调用
public static HttpKit init(Context context) {
me().setContext(context);
return me();
}
private void setContext(Context context) {
this.mContext = context;
cookieStore = new PersistentCookieStore(mContext);//永久化保存cookie
CookieJarImpl cookieJar = new CookieJarImpl(cookieStore);
okHttpClientBuilder.cookieJar(cookieJar);
}
//设置cookie
public void setCookie(Uri uri, Cookie cookie) {
HttpUrl httpUrl = new HttpUrl.Builder().scheme(uri.getScheme()).host(uri.getHost()).build();
cookieStore.add(httpUrl, cookie);
}
public void removeAllCookie() {
cookieStore.removeAll();
}
CookieJarImpl的实现,PersistentCookieStore的永久化代码,网上有,直接搜
public class CookieJarImpl implements CookieJar {
private CookieStore cookieStore;
public CookieJarImpl(CookieStore cookieStore) {
if (cookieStore == null)
throw new IllegalArgumentException(String.format("cookieStore can not be null."));
this.cookieStore = cookieStore;
}
@Override
public synchronized void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.add(url, cookies);
}
@Override
public synchronized List<Cookie> loadForRequest(HttpUrl url) {
return cookieStore.get(url);
}
public CookieStore getCookieStore() {
return cookieStore;
}
}
网友评论