首先說明下:本文碰到的一些問題,都是在 okhttp-3.10.0,okio-1.14.0 這個版本碰到的。
1,OkHttpClient 默認的 connectTimeout,readTimeout,writeTimeout 都是10秒,實際在應用體驗上來說,有點短的。項目中最好 connectTimeout = 10s,readTimeout= 60s,readTimeout= 60s,如果涉及到下載上傳,實際應該修改成更長的。
2,Request,默認頭信息 User-Agent 是“okhttp3.0”,建議修改成系統的。
下面代碼是兼容的方式獲取系統默認UA的方法:
/**
* 獲取默認UserAgent(讀取系統WebView的UserAgent設置)
*/
public String getDefaultUserAgent(Context context) {
String result;
// http://androidxref.com/4.1.1/xref/frameworks/base/core/java/android/webkit/WebSettingsClassic.java#getCurrentUserAgent
try {
Locale locale = context.getResources().getConfiguration().locale;
StringBuffer buffer = new StringBuffer();
// Add version
final String version = Build.VERSION.RELEASE;
if (version.length() > 0) {
buffer.append(version);
} else {
// default to "1.0"
buffer.append("1.0");
}
buffer.append("; ");
final String language = locale.getLanguage();
if (language != null) {
buffer.append(language.toLowerCase());
final String country = locale.getCountry();
if (country != null) {
buffer.append("-");
buffer.append(country.toLowerCase());
}
} else {
// default to "en"
buffer.append("en");
}
// add the model for the release build
if ("REL".equals(Build.VERSION.CODENAME)) {
final String model = Build.MODEL;
if (model.length() > 0) {
buffer.append("; ");
// ok3, header不支持中文, encode一下
buffer.append(URLEncoder.encode(model, "utf-8"));
}
}
final String id = Build.ID;
if (id.length() > 0) {
buffer.append(" Build/");
buffer.append(id);
}
final String base = context.getResources().getText(
Resources.getSystem().getIdentifier("web_user_agent", android.R.string.class.getSimpleName(), "android")).toString();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
result = String.format(base, buffer);
} else {
String mobile = context.getResources().getText(
Resources.getSystem().getIdentifier("web_user_agent_target_content", android.R.string.class.getSimpleName(), "android")).toString();
result = String.format(base, buffer, mobile);
}
} catch (Exception | Error e) {
if (LogUtils.isDebug()) {
LogUtils.d("OkhttpImp", "getDefaultUserAgent");
}
result = System.getProperty("http.agent");
}
if (LogUtils.isDebug()) {
LogUtils.d("OkhttpImp", "getDefaultUserAgent.result = " + result);
}
return result;
}
3,Request 添加 header 的時候,需要注意 okhttp3 中 header 是不支持中文的,所以注意 URLEncoder。
4,ok3 支持異步獲取數據: Call.enqueue(Callback cb),但是要注意 Callback 回調裏面的方法全部是在子線程的。
5,http1.1 支持 TCP 通道複用機制,http2.0 還支持了多路複用機制,所以有時候明明有網絡,但是接口卻返回 SocketTimeoutException,UnknownHostException,一般都是後臺接口沒有嚴格按照http1.1協議和http2.0協議來,導致服務器Socket關了,但是沒有通知客戶端,客戶端下次請求,複用鏈路導致 SocketTimeoutException。三種思路解決:
第一種:服務器端修改。
第二種:客戶端關閉連接池 OkHttpClient.connectionPool().evictAll()。
第三種:客戶端加重試機制,失敗重新請求一次。推薦這種方式,失敗重試可以解決很多其他網絡偶然問題,比如快速切網的時候。