正文

internalize-internalize反義詞

xinfeng335
文章最后更新時(shí)間2025年02月07日,若文章內(nèi)容或圖片失效,請(qǐng)留言反饋!

  作者

internalize-internalize反義詞
(圖片來源網(wǎng)絡(luò),侵刪)

  本文由 煥然一璐投稿internalize,博客地址internalize:http://www.apkbus.com/myspaceblog-904275.html

  前言

  小巴士在文末Debug時(shí)間板塊有問題喲,歡迎大家積極評(píng)論回復(fù)。Android開發(fā)中網(wǎng)絡(luò)編程是必不可少的,不接入互聯(lián)網(wǎng)的APP就沒有盈利可言。廢話不多說了,下面請(qǐng)先看Android中網(wǎng)絡(luò)請(qǐng)求的進(jìn)化圖:

  

  HttpURLConnection,Apache HTTP Client,Volley到現(xiàn)在的OKHttp,可謂天外有天,人外有人。為什么OKHttp會(huì)這么火呢,相信下面的介紹會(huì)告訴你答案。

  OKHttp的簡介

  首先,給出OKHttp的項(xiàng)目地址:https://github.com/square/okhttp

  Android為我們提供了兩種HTTP交互的方式: HttpURLConnection 和 Apache HTTP Client,雖然兩者都支持HTTPS,流的上傳和下載,配置超時(shí),IPv6和連接池,已足夠滿足我們各種HTTP請(qǐng)求的需求。但更高效的使用HTTP可以讓您的應(yīng)用運(yùn)行更快、更節(jié)省流量。而OkHttp庫就是為此而生。 OkHttp是一個(gè)高效的HTTP庫:

  1.支持 SPDY ,共享同一個(gè)Socket來處理同一個(gè)服務(wù)器的所有請(qǐng)求

  2.如果SPDY不可用,則通過連接池來減少請(qǐng)求延時(shí)

  3.無縫的支持GZIP來減少數(shù)據(jù)流量

  1.緩存響應(yīng)數(shù)據(jù)來減少重復(fù)的網(wǎng)絡(luò)請(qǐng)求

  2.一般的get請(qǐng)求

  3.一般的post請(qǐng)求

  4.基于Http的文件上傳

  5.文件下載

  6.加載圖片

  7.支持請(qǐng)求回調(diào),直接返回對(duì)象、對(duì)象集合

  8.支持session的保持

  OkHttp會(huì)從很多常用的連接問題中自動(dòng)恢復(fù)。如果您的服務(wù)器配置了多個(gè)IP地址,當(dāng)?shù)谝粋€(gè)IP連接失敗的時(shí)候,會(huì)自動(dòng)嘗試下一個(gè)IP。OkHttp還處理了代理服務(wù)器問題和SSL握手失敗問題。(并發(fā)) 使用 OkHttp 無需重寫您程序中的網(wǎng)絡(luò)代碼。OkHttp實(shí)現(xiàn)了幾乎和java.net.HttpURLConnection一樣的API。如果您用了 Apache HttpClient,則OkHttp也提供了一個(gè)對(duì)應(yīng)的okhttp-apache 模塊。 從上面的簡單介紹中可以知道,雖然在編程上面并不會(huì)簡潔很多,但是OKHttp內(nèi)部的一些功能能夠幫助我們自動(dòng)完成一些很復(fù)雜的操作,筆者個(gè)人認(rèn)為最大的賣點(diǎn)就是大大節(jié)省用戶的流量。

  OKHttp的基本使用

  1、在Gradle中引入Cardview的依賴庫。

  compile'com.squareup.okhttp:okhttp:3.8.0'

  2、OKHttp在使用之前,首先要了解下面幾個(gè)比較核心的類以及它的功能。

OkHttpClient 客戶端對(duì)象

Request是OkHttp中訪問的請(qǐng)求,Post請(qǐng)求中需要包含RequestBody

Builder是輔助類,用于生產(chǎn)對(duì)象

Response即OkHttp中的響應(yīng),響應(yīng)中可以得到返回是否成功,返回?cái)?shù)據(jù)

MediaType 數(shù)據(jù)類型,用來表明是JSON等一系列格式

RequestBody 請(qǐng)求數(shù)據(jù),在Post請(qǐng)求中用到

client.newCall(request).execute()是同步的請(qǐng)求方法

client.newCall(request).enqueue(Callback callBack)是異步的請(qǐng)求方法,但是Callback里面的代碼是執(zhí)行在子線程的,因此不能更新UI。

  3、OKHttp的基本使用步驟(以POST方式從服務(wù)器取JSON數(shù)據(jù)為例)

創(chuàng)建OkHttpClient對(duì)象,官方文檔要求我們最好使用單例模式,在后文對(duì)OKHttp進(jìn)行封裝的時(shí)候會(huì)提到。

如果是post請(qǐng)求的話,需要通過FormEncodingBuilder創(chuàng)建RequestBody對(duì)象,指定需要post傳進(jìn)去的參數(shù)。get請(qǐng)求則不用。

創(chuàng)建Request對(duì)象,這個(gè)對(duì)象是請(qǐng)求對(duì)象,需要指定URL。post請(qǐng)求的時(shí)候需要指定RequestBody對(duì)象,get請(qǐng)求則不用。

調(diào)用OkHttpClient的newCall方法,把Request對(duì)象傳進(jìn)去,然后執(zhí)行execute或者enqueue方法,兩者的區(qū)別在上文已提到。在CallBack中的onResponse方法就可以做你需要做的事。onResponse回調(diào)的參數(shù)是response,一般情況下,比如我們希望獲得返回的字符串,可以通過response.body().string()獲取internalize;如果希望獲得返回的二進(jìn)制字節(jié)數(shù)組,則調(diào)用response.body().bytes();如果你想拿到返回的inputStream,則調(diào)用response.body().byteStream()看到這,你可能會(huì)奇怪,竟然還能拿到返回的inputStream,看到這個(gè)最起碼能意識(shí)到一點(diǎn),這里支持大文件下載,有inputStream我們就可以通過IO的方式寫文件。不過也說明一個(gè)問題,這個(gè)onResponse執(zhí)行的線程并不是UI線程。的確是的,如果你希望操作控件,還是需要使用handler等。

OkHttpClient client =

newOkHttpClient(); RequestBody body =

newFormEncodingBuilder() .add(

"type",

"1") .build();

Request

request=

new

Request.Builder() .url(Constants.URL_BANNER) .post(body) .build(); client.newCall(

request).enqueue(

newCallback() { @Override

  publicvoid onFailure( Requestrequest, IOException e) { } @Override

  publicvoid onResponse( Responseresponse) throws IOException {

  if( response.isSuccessful()) { android.os.Message msg = newMessage(); msg.what = 1; msg.obj = response.body(). string(); mHandler.sendMessage(msg); } } });

  這里只是一個(gè)簡單post請(qǐng)求,從服務(wù)器獲取數(shù)據(jù)的介紹,至于get請(qǐng)求只不過是去掉RequestBody對(duì)象而已。至于如何向服務(wù)器提交數(shù)據(jù),可以在熟悉上面的基本用法之后查閱官方的WIKI(GitHub的介紹文檔)。

  OKHttp的簡單封裝

  回顧上面的代碼,試想一下如果每次請(qǐng)求都寫這么多重復(fù)代碼,這樣會(huì)嚴(yán)重降低開發(fā)效率,因此需要對(duì)OKHttp進(jìn)行封裝。對(duì)代碼進(jìn)行封裝是我們最為面向?qū)ο蟪绦騿T的基本素養(yǎng),減少重復(fù)代碼,降低維護(hù)難度以及成本。

  GitHub上也有對(duì)OKHttp進(jìn)行過封裝,叫做OKHttpUtils。不過這里我們自己動(dòng)手,一起來學(xué)習(xí)一下如何進(jìn)行封裝。具體的注意點(diǎn)有下面幾點(diǎn):

  1、首先,OKHttp官方要求我們最好用單例模式去使用OKHttpClient類的,因此我們自定義一個(gè)OKHttpHelper類,并且使用單例模式。

  2、對(duì)get以及post方法進(jìn)行封裝,主要的思想是把共同的代碼抽取出來,例如代碼中被抽取出來的request方法。

  3、對(duì)外公開一些靜態(tài)方法,包括get和post方法等。

  4、Callback基類,對(duì)OKHttp的回調(diào)進(jìn)行封裝。這個(gè)類用里面有一個(gè)type,是方便回調(diào)中使用Gson對(duì)JSON進(jìn)行解析的封裝。使用Callback的時(shí)候只需要在泛型中傳入類似Data 、List<Data>即可以方便地使用JSON。

  5、由于原來的回調(diào)不在主線程,因此我們需要使用Handler來將回調(diào)放入主線程。

  其余的可以參照代碼,有詳細(xì)注釋。

  /** * 這個(gè)類用來輔助OKHttp */publicclassOkHttpHelper{ /** * 采用單例模式使用OkHttpClient */privatestaticOkHttpHelper mOkHttpHelperInstance;

  privatestaticOkHttpClient mClientInstance;

  privateHandler mHandler;

  privateGson mGson; /** * 單例模式,私有構(gòu)造函數(shù),構(gòu)造函數(shù)里面進(jìn)行一些初始化 */privateOkHttpHelper(){ mClientInstance = newOkHttpClient(); mClientInstance.setConnectTimeout( 10, TimeUnit.SECONDS); mClientInstance.setReadTimeout( 10, TimeUnit.SECONDS); mClientInstance.setWriteTimeout( 30, TimeUnit.SECONDS); mGson = newGson(); mHandler = newHandler(Looper.getMainLooper()); } /** * 獲取實(shí)例 * * @return*/publicstaticOkHttpHelper getinstance(){

  if(mOkHttpHelperInstance == null) {

  synchronized(OkHttpHelper.class) {

  if(mOkHttpHelperInstance == null) { mOkHttpHelperInstance = newOkHttpHelper(); } } } returnmOkHttpHelperInstance; } /** * 封裝一個(gè)request方法,不管post或者get方法中都會(huì)用到 */publicvoidrequest(finalRequest request, finalBaseCallback callback){ //在請(qǐng)求之前所做的事,比如彈出對(duì)話框等callback.onRequestBefore(); mClientInstance.newCall(request).enqueue( newCallback() {

  @OverridepublicvoidonFailure(Request request, IOException e){ //返回失敗callbackFailure(request, callback, e); } @OverridepublicvoidonResponse(Response response)throwsIOException {

  if(response.isSuccessful()) { //返回成功回調(diào)String resString = response.body().string();

  if(callback.mType == String.class) { //如果我們需要返回String類型callbackSuccess(response, resString, callback); } else{ //如果返回的是其他類型,則利用Gson去解析try{ Object o = mGson.fromJson(resString, callback.mType); callbackSuccess(response, o, callback); } catch(JsonParseException e) { e.printStackTrace(); callbackError(response, callback, e); } } } else{ //返回錯(cuò)誤callbackError(response, callback, null); } } }); } /** * 在主線程中執(zhí)行的回調(diào) * * @paramresponse * @paramresString * @paramcallback */privatevoidcallbackSuccess(finalResponse response, finalObject o, finalBaseCallback callback){ mHandler.post( newRunnable() {

  @Overridepublicvoidrun(){ callback.onSuccess(response, o); } }); } /** * 在主線程中執(zhí)行的回調(diào) * @paramresponse * @paramcallback * @parame */privatevoidcallbackError(finalResponse response, finalBaseCallback callback, finalException e){ mHandler.post( newRunnable() {

  @Overridepublicvoidrun(){ callback.(response, response.code(), e); } }); } /** * 在主線程中執(zhí)行的回調(diào) * @paramrequest * @paramcallback * @parame */privatevoidcallbackFailure(finalRequest request, finalBaseCallback callback, finalException e){ mHandler.post( newRunnable() {

  @Overridepublicvoidrun(){ callback.onFailure(request, e); } }); } /** * 對(duì)外公開的get方法 * * @paramurl * @paramcallback */publicvoidget(String url, BaseCallback callback){ Request request = buildRequest(url, null, HttpMethodType.GET); request(request, callback); } /** * 對(duì)外公開的post方法 * * @paramurl * @paramparams * @paramcallback */publicvoidpost(String url, Map<String, String> params, BaseCallback callback){ Request request = buildRequest(url, params, HttpMethodType.POST); request(request, callback); } /** * 構(gòu)建請(qǐng)求對(duì)象 * * @paramurl * @paramparams * @paramtype * @return*/privateRequest buildRequest(String url, Map<String, String> params, HttpMethodType type){ Request.Builder builder = newRequest.Builder(); builder.url(url);

  if(type == HttpMethodType.GET) { builder.get(); } elseif(type == HttpMethodType.POST){ builder.post(buildRequestBody(params)); } returnbuilder.build(); } /** * 通過Map的鍵值對(duì)構(gòu)建請(qǐng)求對(duì)象的body * * @paramparams * @return*/privateRequestBody buildRequestBody(Map<String, String> params){ FormEncodingBuilder builder = newFormEncodingBuilder();

  if(params != null) {

  for(Map.Entry<String, String> entity : params.entrySet()) { builder.add(entity.getKey(), entity.getValue()); } } returnbuilder.build(); } /** * 這個(gè)枚舉用于指明是哪一種提交方式 */enumHttpMethodType { GET, POST }}

  回調(diào)的封裝

  package com.nan.cnshop.http;import com.google.gson.internal.$Gson$Types;import com.squareup.okhttp.Request;import com.squareup.okhttp.Response;import java.lang.reflect.ParameterizedType;import java.lang.reflect.Type; /** * 基本的回調(diào) */publicabstractclassBaseCallback<T> { /** * type用于方便JSON的解析 */publicType mType; /** * 把type轉(zhuǎn)換成對(duì)應(yīng)的類,這里不用看明白也行。 * * @paramsubclass * @return*/staticType getSuperclassTypeParameter( Class<?> subclass) { Type superclass = subclass.getGenericSuperclass();

  if(superclass instanceofClass) {

  thrownewRuntimeException( "Missing type parameter."); } ParameterizedType parameterized = (ParameterizedType) superclass;

  return$Gson$Types.canonicalize(parameterized.getActualTypeArguments()[ 0]); } /** * 構(gòu)造的時(shí)候獲得type的class */publicBaseCallback() { mType = getSuperclassTypeParameter(getClass()); } /** * 請(qǐng)求之前調(diào)用 */publicabstractvoid onRequestBefore();

  /** * 請(qǐng)求失敗調(diào)用(網(wǎng)絡(luò)問題) * * @paramrequest * @parame */publicabstractvoid onFailure(Request request, Exceptione);

  /** * 請(qǐng)求成功而且沒有錯(cuò)誤的時(shí)候調(diào)用 * * @paramresponse * @paramt */publicabstractvoid onSuccess(Response response, T t);

  /** * 請(qǐng)求成功但是有錯(cuò)誤的時(shí)候調(diào)用,例如Gson解析錯(cuò)誤等 * * @paramresponse * @paramerrorCode * @parame */publicabstractvoid (Response response, int errorCode, Exceptione);} OKHttp封裝之后的使用

  如下面的代碼所示。首先得到OkHttpHelper的單例,然后調(diào)用get方法就可以了。由于繼承了Gson,因此需要在BaseCallback的泛型中傳入JSON對(duì)應(yīng)的數(shù)據(jù)類型,筆者這里是List<Banner>。最后在onSuccess方法中做我們想要做的事情就可以了。

  mHttpHelper=OkHttpHelper.getinstance();mHttpHelper.get(Constants.URL_BANNER, newBaseCallback<List<Banner>>() {

  @OverridepublicvoidonRequestBefore(){ } @OverridepublicvoidonFailure(Request request, Exception e){ } @OverridepublicvoidonSuccess(Response response, List<Banner> banners){ initBanners(banners); } @Overridepublicvoid(Response response, interrorCode, Exception e){ }});

  是不是覺得封裝之后OKHttp的使用變得很簡單呢,這就是封裝的強(qiáng)大之處,好了今天的筆記到此為止。

  PS:這里只介紹了OKHttp的get和post使用介紹,其余的使用例如文件下載上傳以及對(duì)應(yīng)的代碼封裝請(qǐng)自己去完成~(≧▽≦)/~啦啦啦。全文還有 BaseCallback 和 OkHttpHelper 的代碼,歡迎閱讀原文查看。

  Debug 時(shí)間

  

  如果完全沒了優(yōu)秀的第三方庫簡直令人抓狂,說說你對(duì)哪些優(yōu)秀的第三方庫相見恨晚呢internalize?它們給你帶來了哪些便利?

  回答認(rèn)真的有趣的,小巴士會(huì)分享出來,開啟無敵腦洞吧~另外,給安卓巴士公眾號(hào)后臺(tái)發(fā)送“報(bào)名交友”+你的聯(lián)系方式(企鵝號(hào)/微信號(hào)),經(jīng)過篩選就可以得到小巴士獨(dú)家專訪吸引更多妹子關(guān)注,幫你早日脫單,具體詳情見此篇《這位程序員哥哥 其實(shí)我覬覦你很久了》。

-- 展開閱讀全文 --