OkHttp æ¯ä¸ä¸ªå¨å¼åå¯æ±å¦é¢Android APPè¿ç¨ä¸é常éè¦çä¾èµåºãå®çé»è®¤çé
置为æ们æä¾äºé常éè¦å®ç¨åè½ï¼ä¸é¢ä¸äºæ¥éª¤æ们å¯ä»¥è®©Okhttpæä¾æ´å¤åè½ä½¿ç¨çµæ´»åå
çè½åã
1. å¯ç¨æ件系ç»ä¸çååºç¼å
é»è®¤æ
åµä¸ï¼Okhttpä¸æ¯æååºç¼åï¼å
æ¬HTTP Cache-Control头å
许ç¼åååºãå æ¤ï¼å®¢æ·ç«¯éè¿ä¸æ¬¡åä¸æ¬¡ç请æ±ç¸åçèµæºæµªè´¹æ¶é´å带宽ãèä¸æ¯ç®åå°è¯»ååå§ååºåç¼åçå¯æ¬ã
è¦å¨æ件系ç»ä¸å¯ç¨ååºç¼åï¼éè¦é
ç½®com.squareup.okhttp.Cacheå®ä¾ï¼å¹¶æå®ä¼ éç»ä½ çOkHttpClientå®ä¾çsetCacheæ¹æ³ãä½ å¿
é¡»åå§åç¼åä¸åæ¾ç®å½çæ件ï¼å¹¶ä»¥åè为åä½çæ大å¼ã
ååºè¿åæ°æ®å¯ä»¥åå
¥ç»å®ç®å½æ件ï¼å¦æä¸ä¸ªååºçç¼åè¶
è¿äºç»å®ç大å°ãæ们å¯ä»¥éå LRU policy ã
æ们å¯ä»¥å¨ stackoverflow æ¥ç Jesse Wilson çåå¤ãæ们å¯ä»¥éè¿context.getCacheDir()å¨åç®å½ä¸ç¼åæ们çååºï¼
// Base directory recommended by
http://stackoverflow.com/a/32752861/400717.// Guard against null, which is possible according to
//
https://groups.google.com/d/msg/android-developers/-694j87eXVU/YYs4b6kextwJ and
//
http://stackoverflow.com/q/4441849/400717.final @Nullable File baseDir = context.getCacheDir();
if (baseDir != null) {
final File cacheDir = new File(baseDir, "HttpResponseCache");
okHttpClient.setCache(new Cache(cacheDir, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE));
}
// Base directory recommended by
http://stackoverflow.com/a/32752861/400717.// Guard against null, which is possible according to
//
https://groups.google.com/d/msg/android-developers/-694j87eXVU/YYs4b6kextwJ and
//
http://stackoverflow.com/q/4441849/400717.final @NullableFilebaseDir = context.getCacheDir();
if (baseDir != null) {
final FilecacheDir = new File(baseDir, "HttpResponseCache");
okHttpClient.setCache(new Cache(cacheDir, HTTP_RESPONSE_DISK_CACHE_MAX_SIZE));
}
å¨å¯æ±å¦é¢çç¨åºä¸æ们æå® HTTP_RESPONSE_DISK_CACHE_MAX_SIZE as 10 * 1024 * 1024 , or 10 MBç大å°
2. éæStetho
Stetho æ¯Facebookçä¸ä¸ªå¯ç±çåºï¼å¯ä»¥ä½¿ç¨Chromeæµè§å¨çChromeå¼å人åå·¥å
·åè½æ¥æ£æ¥ä½ çAndr oidåºç¨ç¨åºã
Stethoé¤äºå
è®¸ä½ æ£æ¥ä½ çåºç¨ç¨åºçSQLiteæ°æ®åºï¼è¿å¯ä»¥æ¥çViewçå±æ¬¡ç»æãå
è®¸ä½ æ£æ¥ç±OkHttpåèµ·çæ¯ä¸ªè¯·æ±åååºï¼
è¿ç§èªçæºå¶æ¯ç¡®ä¿æå¡å¨è¿åå
许èµæºç¼åçHTTP头æ¯é常æç¨çï¼ä»¥åéªè¯æ²¡æ请æ±æ¶ï¼ä¿è¯ç¼åçèµæºåå¨ã
è¦æ³ä½¿ç¨Stethoï¼åªéæ·»å ä¸ä¸ªStethoInterceptorå®ä¾çç½ç»æ¦æªå¨å表ï¼
okHttpClient.networkInterceptors().add(new StethoInterceptor());
okHttpClient.networkInterceptors().add(new StethoInterceptor());
ç¶åï¼è¿è¡åºç¨ç¨åºï¼æå¼æµè§å¨åï¼è¾å
¥chrome://inspectãç¶åä½ å°±ä¼çå°åºç¨ç¨åºç设å¤åæ è¯ç¬¦çå表ãç¶åé¼ æ å³é®éæ©inspect æå¼å¼åè
å·¥å
·ï¼ç¶åæå¼æ°çtabï¼å¼å§çæ§OkHttp请æ±ã
3. 使ç¨Picasso å Retrofit
ä½ å¯è½ä½¿ç¨è¿ Picasso æ¥å è½½ç½ç»å¾çï¼æè
ä½¿ç¨ Retrofit æ¥ç®åååºè¯·æ±å解ç ååºãè¿äºç¬¬ä¸æ¹åºå°éå¼å°å建èªå·±çOkHttpClientä¾å
é¨ä½¿ç¨ï¼å¦æä½ ä¸æç¡®æå®ä¸ä¸ªã
Picasso version 2.5.2çOkHttpDownloaderç±»ï¼
private static OkHttpClient defaultOkHttpClient() {
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(Utils.DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setReadTimeout(Utils.DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setWriteTimeout(Utils.DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
return client;
}
private static OkHttpClientdefaultOkHttpClient() {
OkHttpClientclient = new OkHttpClient();
client.setConnectTimeout(Utils.DEFAULT_CONNECT_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setReadTimeout(Utils.DEFAULT_READ_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
client.setWriteTimeout(Utils.DEFAULT_WRITE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
return client;
}
Retrofitä¹æ类似çå·¥åæ¹æ³æ¥å建èªå·±çOkHttpClientã
å¾çä¸è¬å¨åºç¨ç¨åºä¸éè¦å è½½çæ¯è¾å¤§çèµæºã尽管Picassoèªå·±ç»´æ¤å®çLRUæºå¶æ¥ç¼åå¾çï¼å¨å
åä¸ä¸¥æ ¼æ§è¡ãå¦æ客æ·ç«¯å°è¯ä½¿ç¨Picassoæ¥å è½½å¾çãPicassoä¼æ¾ä¸å°å
¶å¨å
åä¸ç¼åå¾åï¼ç¶åå°å§æå 载该å¾çå°å®çå
é¨OkHttpClientå®ä¾ã并ä¸é»è®¤æ
åµä¸è¯¥å®ä¾å°å§ç»ä»æå¡å¨å è½½å¾çèµæºã
ä½ä¸ºdefaultOkHttpClientçæ¹æ³ä¸è½ä¸ä¸é¢æå°çæ件系ç»ä¸çååºç¼åé
ç½®ç»åèµ·æ¥ã
æå®ä½ èªå·±çOkHttpClientå®ä¾å
许è¿åæ°æ®ä»æ件系ç»ç¼åååºï¼å¾çä¸ä¼ä»æå¡å¨å è½½ãè¿æ¯é常éè¦çå¨ç¨åºç¬¬ä¸æ¬¡å¯å¨ä»¥åãè¿ä¸ªæ¶åPicassoçå
åç¼åæ¯å·çãæ以å®ä¼é¢ç¹çå§æOkHttpClientå®ä¾å»å è½½å¾çã
è¿å°±éè¦æ建é
ç½®äºæ¨Picasso çOkHttpClientå®ä¾ï¼å¦æä½ å¨ä½ ç代ç ä¸ä½¿ç¨
Picasso.with(context).load(...)
Picasso.with(context).load(...)
å è½½å¾çï¼ä½ æ¯ç¨çæ¯Picassoçåä¾æ¨¡å¼ãè¿æ¯éè¿withæ¹æ³ææ±æ¨¡å¼å°å®ä¾å并é
ç½®èªå·±çOkHttpClientãå æ¤ï¼æ们å¿
须使æ们èªå·±çPicassoå®ä¾å¨åä¾ä¹åéè¿wihtæ¹æ³è°ç¨ã
å®ç°è¿ä¸ªï¼å¯ä»¥ç®åçå°OkHttpClientå®ä¾å°è£
å¨OkHttpDownloaderä¸ï¼ç¶åä¼ éç» Picasso.Builder å®ä¾çdownloaderæ¹æ³ã
final Picasso picasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(okHttpClient))
.build();
// The client should inject this instance whenever it is needed, but replace the singleton
// instance just in case.
Picasso.setSingletonInstance(picasso);
final Picassopicasso = new Picasso.Builder(context)
.downloader(new OkHttpDownloader(okHttpClient))
.build();
// The client should inject this instance whenever it is needed, but replace the singleton
// instance just in case.
Picasso.setSingletonInstance(picasso);
å¨Retrofitä¸è¦ä½¿ç¨OkHttpClientå®ä¾ï¼éè¦æ¹é 1.9.xçä¸ä¸ªRestAdapterï¼éè¦å°OkHttpClientå°è£
OkClientçå®ä¾ä¸ãç¶åæå®ä¼ éç»RestAdapter.Builderå®ä¾çsetClientæ¹æ³ã
restAdapterBuilder.setClient(new OkClient(httpClient));
restAdapterBuilder.setClient(new OkClient(httpClient));
å¨ Retrofit 2.0ä¸åªéè¦ç®åçå°OkHttpClientä¼ éç»Retrofit.Builderå®ä¾çclientæ¹æ³ã
å¨å¯æ±å¦é¢çAPPä¸æ们éè¿ Dagger ä¾èµæ³¨å
¥æ¥ç¡®ä¿æ们åªæä¸ä¸ªOkHttpClientçå®ä¾ãè¿ç§æ¹æ³åæ ·ä¹éç¨äºPicassoåRetrofitæ们æä¾äºä¸ä¸ªä¸ºOkHttpClientå®ä¾æä¾åä¾æ¨¡å¼ç注解示ä¾ï¼
@Provides
@Singleton
public OkHttpClient okHttpClient(final Context context, ...) {
final OkHttpClient okHttpClient = new OkHttpClient();
configureClient(okHttpClient, ...);
return okHttpClient;
}
@Provides
@Singleton
public OkHttpClientokHttpClient(final Contextcontext, ...) {
final OkHttpClientokHttpClient = new OkHttpClient();
configureClient(okHttpClient, ...);
return okHttpClient;
}
OkHttpClientå°ä¼éè¿Daggerç注解å建ä¸ä¸ªå®ä¾æä¾ç»æ们çPicassoåRetrofitã
4.æå®ä¸ä¸ªç¨æ·ä»£çæ¦æªå¨
æ¥å¿æ件ååæ为æ们æä¾äºæ´å¤æç¨çä¿¡æ¯ï¼å½å®¢æ·å¨æ¯ä¸ªè¯·æ±æä¾è¯¦ç»çUser-Agent
headerå¼çæ¶åãé»è®¤æ
åµä¸ï¼Okhttpå
å«User-Agentå¼åªæå¨ç¹å®çOkhttpçæ¬ä¸ã为äºæå®æ们èªå·±çuser
agentãé¦å
å建æ¦æªå¨çæ¿æ¢å¼ï¼ æ们å¯ä»¥çstackoverflowç建议 ã
public final class UserAgentInterceptor implements Interceptor {
private static final String USER_AGENT_HEADER_NAME = "User-Agent";
private final String userAgentHeaderValue;
public UserAgentInterceptor(String userAgentHeaderValue) {
this.userAgentHeaderValue = Preconditions.checkNotNull(userAgentHeaderValue);
}
@Override
public Response intercept(Chain chain) throws IOException {
final Request originalRequest = chain.request();
final Request requestWithUserAgent = originalRequest.newBuilder()
.removeHeader(USER_AGENT_HEADER_NAME)
.addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue)
.build();
return chain.proceed(requestWithUserAgent);
}
}
public final class UserAgentInterceptor implements Interceptor {
private static final String USER_AGENT_HEADER_NAME = "User-Agent";
private final String userAgentHeaderValue;
public UserAgentInterceptor(String userAgentHeaderValue) {
this.userAgentHeaderValue = Preconditions.checkNotNull(userAgentHeaderValue);
}
@Override
public Responseintercept(Chainchain) throws IOException {
final RequestoriginalRequest = chain.request();
final RequestrequestWithUserAgent = originalRequest.newBuilder()
.removeHeader(USER_AGENT_HEADER_NAME)
.addHeader(USER_AGENT_HEADER_NAME, userAgentHeaderValue)
.build();
return chain.proceed(requestWithUserAgent);
}
}
为äºå建User-Agent headerå¼äººç¶åä¼ éç»UserAgentInterceptorçæé å¨ï¼ä½¿ç¨ä½ å¾å°çä»»ä½ä¿¡æ¯ã
æ们å¯ä»¥ä½¿ç¨ï¼
android çç³»ç»ä¿¡æ¯å¯ä»¥æ¸
æ°çä¼ éåºè¿æ¯ä¸å°android 设å¤
Build.MODEL æè
âå¶é åæä¾çç¨æ·å¯è§æç»å¯è§çå称â
Build.BRANDæè
âæ¶è´¹è
å¯è§çåçä¸äº§å/硬件ç¸å
³ä¿¡æ¯â
Build.VERSION.SDK_INTæè
âæ¶è´¹è
å¯è§çAndroidæä¾çSDKçæ¬å·â
BuildConfig.APPLICATION_ID
BuildConfig.VERSION_NAME
BuildConfig.VERSION_CODE
æåä¸ä¸ªå¼ç±çapplicationIDï¼VERSIONCODEåVERSIONNAMEçå¼å¨æ们çGradle buildèæ¬ä¸
äºè§£æ´å¤ä¿¡æ¯å¯ä»¥æ¥ç versioning your applications å configuring your applicationId with Gradle
请注æï¼å¦ææ¨çåºç¨ç¨åºä½¿ç¨çæ¯WebViewï¼æ¨å¯ä»¥é
置使ç¨ç¸åç User-Agent headerå¼ï¼ä½ å¯ä»¥éè¿ä¸é¢æ¹æ³å建UserAgentInterceptorï¼
WebSettings settings = webView.getSettings();
settings.setUserAgentString(userAgentHeaderValue);
WebSettingssettings = webView.getSettings();
settings.setUserAgentString(userAgentHeaderValue);
5.æå®åççè¶
æ¶
2.5.0çæ¬ä¹åï¼OkHttp请æ±é»è®¤ä¸ºæ°¸ä¸è¶
æ¶ã2.5.0çæ¬å¼å§å¦æ建ç«è¿æ¥è¯·æ±è¶
æ¶ï¼å¦æä»è¿æ¥è¯»åä¸ä¸ä¸ªåèæåå
¥çä¸ä¸ä¸ªåèå°è¿æ¥ï¼è±è´¹è¶
è¿10ç§ï¼å°±ç»æ¢ãè¿æ ·åéè¦æ´æ°å°2.5.0çæ¬æ们就ä¸éè¦å¨æ们ç代ç ä¸ä¿®æ¹bugãåå å¾ç®åæ¯æå 为æ们第ä¸æ¬¡ä½¿ç¨çæ¶å使ç¨äºé误çè·¯å¾ã
è¦è¦çè¿äºé»è®¤å¼ï¼å¯ä»¥åå«è°ç¨setConnectTimeoutï¼setReadTimeoutæsetWriteTimeoutã
éè¦æ³¨æçæ¯PicassoåRetrofit为OkHttpClientå®ä¾æå®ä¸åçè¶
æ¶å¼æ¶ï¼é»è®¤æ
åµä¸ï¼Picassoæå®ï¼
è¿æ¥è¶
è¿15ç§.
读åè¶
è¿20ç§
åå
¥è¶
è¿20ç§
èRetrofitæå®ï¼
è¿æ¥è¶
è¿15ç§.
读åè¶
è¿20ç§
没æåå
¥è¶
æ¶
éè¿é
ç½®PicassoåRetrofitèªå·±çOkHttpClientå®ä¾ä½ å¯ä»¥ç¡®ä¿ææç请æ±è¶
æ¶æ¯ä¸è´ç