Okhttp簡單輔助類與debug注意事項java
先貼代碼(代碼不全,僅供參考)android
import android.os.Handler;
import android.os.Looper;
import android.support.v4.util.ArrayMap;json
import com.ztesoft.zsmart.oss.foa.net.http.callback.FOACallBack;
import com.ztesoft.zsmart.oss.foa.net.http.cookie.CookieJarImpl;
import com.ztesoft.zsmart.oss.foa.net.http.cookie.store.CookieStore;
import com.ztesoft.zsmart.oss.foa.net.http.cookie.store.HasCookieStore;
import com.ztesoft.zsmart.oss.foa.net.http.cookie.store.MemoryCookieStore;
import com.ztesoft.zsmart.oss.foa.net.http.exception.Exceptions;cookie
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;session
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;異步
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.CookieJar;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;ide
/**
* Created by boann on 2016/5/9.
*/
public class OkHttpUtils {
public static final String REQUEST_STRING_KEY_NAME = "mobile_request_attribute"; //json參數的key
public static final int CONNECTION_TIME_OUT_DEFAULT = 20000; //默認鏈接超時時間
public static final int READ_TIME_OUT_DEFAULT = 60000; //默認讀取超時時間
public static final int WRITE_TIME_OUT_DEFAULT = 60000; //默認寫超時時間
private static OkHttpUtils mInstance; //單例模式
private OkHttpClient mOkHttpClient; //
private Handler mDelivery; //用於發送結果給UI線程函數
/**
* 構造函數
* @param okHttpClient
*/
public OkHttpUtils(OkHttpClient okHttpClient) {
if (okHttpClient == null) {
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
//cookie enabled
okHttpClientBuilder.cookieJar(new CookieJarImpl(new MemoryCookieStore()));
okHttpClientBuilder.sslSocketFactory(HttpsUtils.getSslSocketFactory());
okHttpClientBuilder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});oop
mOkHttpClient = okHttpClientBuilder.build();
} else {
mOkHttpClient = okHttpClient;
}post
init();
}
/**
* 取得handler
*/
private void init() {
mDelivery = new Handler(Looper.getMainLooper());
}
/**
* 單例模式實現
* @param okHttpClient
* @return
*/
public static OkHttpUtils getInstance(OkHttpClient okHttpClient) {
if (mInstance == null) {
synchronized (OkHttpUtils.class) {
if (mInstance == null) {
mInstance = new OkHttpUtils(okHttpClient);
}
}
}
return mInstance;
}
/**
* 單例模式實現
* @return
*/
public static OkHttpUtils getInstance() {
if (mInstance == null) {
synchronized (OkHttpUtils.class) {
if (mInstance == null) {
mInstance = new OkHttpUtils(null);
}
}
}
return mInstance;
}
/**
* 返回handler
* @return
*/
private Handler getDelivery() {
return mDelivery;
}
/**
* 設置鏈接,讀取,寫超時時間
* @return
*/
public OkHttpClient getOkHttpClient() {
mOkHttpClient.newBuilder().connectTimeout(CONNECTION_TIME_OUT_DEFAULT, TimeUnit.MILLISECONDS)
.readTimeout(READ_TIME_OUT_DEFAULT, TimeUnit.MILLISECONDS)
.writeTimeout(READ_TIME_OUT_DEFAULT, TimeUnit.MICROSECONDS)
.build();
return mOkHttpClient;
}
/**
*
* @return
*/
public CookieStore getCookieStore() {
final CookieJar cookieJar = mOkHttpClient.cookieJar();
if (cookieJar == null) {
Exceptions.illegalArgument("you should invoked okHttpClientBuilder.cookieJar() to set a cookieJar.");
}
if (cookieJar instanceof HasCookieStore) {
return ((HasCookieStore) cookieJar).getCookieStore();
} else {
return null;
}
}
/**
* 取消請求
* @param tag
*/
public void cancelTag(Object tag) {
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();
}
}
}
/**
* 發送失敗結果
* @param call
* @param e
* @param callback
*/
private void sendFailResultCallback(final Call call, final Response response, final Exception e, final FOACallBack callback)
{
if (callback == null) return;
mDelivery.post(new Runnable()
{
@Override
public void run()
{
callback.onError(call, response, e);
callback.onAfter();
}
});
}
/**
* 發送成功結果
* @param object
* @param callback
*/
private void sendSuccessResultCallback(final Object object, final FOACallBack callback)
{
if (callback == null) return;
mDelivery.post(new Runnable()
{
@Override
public void run()
{
callback.onResponse(object);
callback.onAfter();
}
});
}
/**
* 打包請求
* @param tag
* @param url
* @param requestString
* @param files
* @return
*/
private static Request getRequest(Object tag, String url, String requestString, ArrayMap<String, ArrayList<String>> files) {
MultipartBody.Builder mBuilder = new MultipartBody.Builder();
mBuilder.setType(MultipartBody.FORM);
mBuilder.addFormDataPart(REQUEST_STRING_KEY_NAME, requestString);
if (files != null) {
int count = files.size();
for (int i = 0; i < count; i++){
ArrayList<String> filePaths = files.valueAt(i);
for (int j = 0; j < filePaths.size(); j++) {
File file = new File(filePaths.get(j));
if (file.exists()) {
mBuilder.addFormDataPart(files.keyAt(i), files.keyAt(i), RequestBody.create(MultipartBody.FORM, new File(filePaths.get(j))));
}
}
}
}
return new Request.Builder()
.tag(tag)
.url(url)
.post(mBuilder.build())
.build();
}
/**
* 執行請求
* @param call
* @param foaCallBack
*/
private void foaCall(Call call, FOACallBack foaCallBack) {
if (foaCallBack == null) {
foaCallBack = DEFAULT_CALLBACK;
}
final FOACallBack finalCallBack = foaCallBack;
foaCallBack.onBefore(call.request());
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
sendFailResultCallback(call, null, e, finalCallBack);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.code() >= 400 && response.code() <= 599) {
try {
sendFailResultCallback(call, response, new RuntimeException(response.body().string()), finalCallBack);
} catch (IOException e) {
e.printStackTrace();
}
return;
}
try {
Object o = finalCallBack.parseNetworkResponse(response);
sendSuccessResultCallback(o, finalCallBack);
} catch (Exception e) {
sendFailResultCallback(call, response, e, finalCallBack);
}
}
});
}
/**
* 異步進行帶圖片的請求
* @param tag
* @param url
* @param requestString
* @param files
* @param callback
*/
public static void postWithFilesAsyn(Object tag, String url, String requestString, ArrayMap<String, ArrayList<String>> files, FOACallBack callback) {
Call call = getInstance().getOkHttpClient().newCall(getRequest(tag, url, requestString, files));
getInstance().foaCall(call, callback);
}
/**
* 同步進行帶圖片的請求
* @param tag
* @param url
* @param requestString
* @param files
* @return
*/
public static String postWithFilesSyn(Object tag, String url, String requestString, ArrayMap<String, ArrayList<String>> files) throws Exception{
return OkHttpUtils.getInstance().getOkHttpClient().newCall(getRequest(tag, url, requestString, files)).execute().body().string();
}
/**
* 異步進行不帶圖片的請求
* @param tag
* @param url
* @param requestString
* @param callback 自定義callback
*/
public static void postAsyn(Object tag, String url, String requestString, FOACallBack callback) {
Call call = getInstance().getOkHttpClient().newCall(getRequest(tag, url, requestString, null));
getInstance().foaCall(call, callback);
}
/**
* 同步進行不帶圖片的請求
* @param tag
* @param url
* @param requestString
* @return
*/
public static String postSyn(Object tag, String url, String requestString) throws Exception {
return OkHttpUtils.getInstance().getOkHttpClient().newCall(getRequest(tag, url, requestString, null)).execute().body().string();
}
/**
* 默認的callback
*/
public static FOACallBack DEFAULT_CALLBACK = new FOACallBack() {
@Override
public void onBefore(Request request) {
}
@Override
public void onAfter() {
}
@Override
public void inProgress(float progress) {
}
@Override
public Object parseNetworkResponse(Response response) throws Exception {
return null;
}
@Override
public void onError(Call call, Response response, Exception e) {
}
@Override
public void onResponse(Object response) {
}
};
}
接下來是debug時的大坑,困擾了一天
主要代碼以下
String requestStr = getRequest(locationBeans).toString();
MultipartBody.Builder mBuilder = new MultipartBody.Builder();
mBuilder.setType(MultipartBody.FORM);
mBuilder.addFormDataPart("mobile_request_attribute", requestStr);
Request request = new Request.Builder()
.url(BasicUtils.getServerUrl(this))
.post(mBuilder.build())
.build();
try {
Response response = OkHttpUtils.getInstance().getOkHttpClient().newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println("Server: " + response.header("Server"));
System.out.println("Date: " + response.header("Date"));
System.out.println("Vary: " + response.headers("Vary"));
System.out.println(response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
運行到response.body().string()一步時拋異常,java.lang.IllegalStateException: closed
查閱各類資料大體意思是The IllegalStateException
arises because the HttpConnection seems to be closed when trying to use it. Could it be because you are calling twice the method response.body()
?
就是說調用response.body().string()的時候數據流已經關閉了,再次調用就是提示已經closed,
檢查代碼發現,其餘的地方並無調用過response.body().string(),並且是調試的時候有,後來發現是在debug的時候添加了Watchs,就是代碼的監視,這裏會調用一次response.body().string()。
後面須要注意,代碼調試的時候表達式的監視有時候會影響代碼的運行。
引覺得戒。