自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

利器OkHttp的使用以及簡(jiǎn)單封裝

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

前言

Android開(kāi)發(fā)中網(wǎng)絡(luò)編程是必不可少的,不接入互聯(lián)網(wǎng)的APP就沒(méi)有盈利可言。廢話不多說(shuō)了,下面請(qǐng)先看Android中網(wǎng)絡(luò)請(qǐng)求的進(jìn)化圖:

Android中網(wǎng)絡(luò)請(qǐng)求的進(jìn)化圖 

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

OKHttp的簡(jiǎn)介

首先,給出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庫(kù)就是為此而生。 OkHttp是一個(gè)高效的HTTP庫(kù):

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

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

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

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

OKHttp的基本使用

1、在Gradle中引入CardView的依賴庫(kù)。

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

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

  • OkHttpClient 客戶端對(duì)象
  • Request是OkHttp中訪問(wèn)的請(qǐng)求,Post請(qǐng)求中需要包含RequestBody
  • Builder是輔助類,用于生產(chǎn)對(duì)象
  • Response即OkHttp中的響應(yīng),響應(yīng)中可以得到返回是否成功,返回?cái)?shù)據(jù)
  • MediaType 數(shù)據(jù)類型,用來(lái)表明是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)求的話,需要通過(guò)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,一般情況下,比如我們希望獲得返回的字符串,可以通過(guò)response.body().string()獲取;如果希望獲得返回的二進(jìn)制字節(jié)數(shù)組,則調(diào)用response.body().bytes();如果你想拿到返回的inputStream,則調(diào)用response.body().byteStream()看到這,你可能會(huì)奇怪,竟然還能拿到返回的inputStream,看到這個(gè)最起碼能意識(shí)到一點(diǎn),這里支持大文件下載,有inputStream我們就可以通過(guò)IO的方式寫文件。不過(guò)也說(shuō)明一個(gè)問(wèn)題,這個(gè)onResponse執(zhí)行的線程并不是UI線程。的確是的,如果你希望操作控件,還是需要使用handler等。
  1. OkHttpClient client = new OkHttpClient(); 
  2.  
  3.     RequestBody body = new FormEncodingBuilder() 
  4.             .add("type""1"
  5.             .build();    Request request = new Request.Builder() 
  6.             .url(Constants.URL_BANNER) 
  7.             .post(body) 
  8.             .build(); 
  9.  
  10.     client.newCall(request).enqueue(new Callback() { 
  11.         @Override         
  12.     public void onFailure(Request request, IOException e) { 
  13.  
  14.         } 
  15.  
  16.         @Override         
  17.     public void onResponse(Response response) throws IOException {             
  18.             if (response.isSuccessful()) { 
  19.  
  20.                 android.os.Message msg = new Message(); 
  21.                 msg.what = 1; 
  22.                 msg.obj = response.body().string(); 
  23.                 mHandler.sendMessage(msg); 
  24.             } 
  25.         } 
  26.     });  

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

OKHttp的簡(jiǎn)單封裝

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

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

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

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

3、對(duì)外公開(kāi)一些靜態(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、由于原來(lái)的回調(diào)不在主線程,因此我們需要使用Handler來(lái)將回調(diào)放入主線程。

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

  1. /** 
  2.  * 這個(gè)類用來(lái)輔助OKHttp 
  3.  */public class OkHttpHelper {    /** 
  4.      * 采用單例模式使用OkHttpClient 
  5.      */ 
  6.     private static OkHttpHelper mOkHttpHelperInstance;     
  7.     private static OkHttpClient mClientInstance;     
  8.     private Handler mHandler;     
  9.     private Gson mGson;    /** 
  10.      * 單例模式,私有構(gòu)造函數(shù),構(gòu)造函數(shù)里面進(jìn)行一些初始化 
  11.      */ 
  12.     private OkHttpHelper() { 
  13.         mClientInstance = new OkHttpClient(); 
  14.  
  15.         mClientInstance.setConnectTimeout(10, TimeUnit.SECONDS); 
  16.         mClientInstance.setReadTimeout(10, TimeUnit.SECONDS); 
  17.         mClientInstance.setWriteTimeout(30, TimeUnit.SECONDS); 
  18.         mGson = new Gson(); 
  19.  
  20.         mHandler = new Handler(Looper.getMainLooper()); 
  21.     }    /** 
  22.      * 獲取實(shí)例 
  23.      * 
  24.      * @return 
  25.      */ 
  26.     public static OkHttpHelper getinstance() {         
  27.         if (mOkHttpHelperInstance == null) {             
  28.             synchronized (OkHttpHelper.class) {                 
  29.                 if (mOkHttpHelperInstance == null) { 
  30.                     mOkHttpHelperInstance = new OkHttpHelper(); 
  31.                 } 
  32.             } 
  33.         }        return mOkHttpHelperInstance; 
  34.     }    /** 
  35.      * 封裝一個(gè)request方法,不管post或者get方法中都會(huì)用到 
  36.      */ 
  37.     public void request(final Request request, final BaseCallback callback) {        //在請(qǐng)求之前所做的事,比如彈出對(duì)話框等 
  38.         callback.onRequestBefore(); 
  39.  
  40.         mClientInstance.newCall(request).enqueue(new Callback() {             
  41.             @Override 
  42.             public void onFailure(Request request, IOException e) {                //返回失敗 
  43.                 callbackFailure(request, callback, e); 
  44.             }            @Override 
  45.             public void onResponse(Response response) throws IOException {                 
  46.                 if (response.isSuccessful()) {                    //返回成功回調(diào) 
  47.                     String resString = response.body().string();                     
  48.                 if (callback.mType == String.class) {                        //如果我們需要返回String類型 
  49.                         callbackSuccess(response, resString, callback); 
  50.                     } else {                        //如果返回的是其他類型,則利用Gson去解析 
  51.                         try { 
  52.                             Object o = mGson.fromJson(resString, callback.mType); 
  53.                             callbackSuccess(response, o, callback); 
  54.                         } catch (JsonParseException e) { 
  55.                             e.printStackTrace(); 
  56.                             callbackError(response, callback, e); 
  57.                         } 
  58.                     } 
  59.  
  60.                 } else {                    //返回錯(cuò)誤 
  61.                     callbackError(response, callback, null); 
  62.                 } 
  63.             } 
  64.         }); 
  65.     }    /** 
  66.      * 在主線程中執(zhí)行的回調(diào) 
  67.      * 
  68.      * @param response 
  69.      * @param resString 
  70.      * @param callback 
  71.      */ 
  72.     private void callbackSuccess(final Response response, final Object o, final BaseCallback callback) { 
  73.         mHandler.post(new Runnable() {             
  74.             @Override 
  75.             public void run() { 
  76.                 callback.onSuccess(response, o); 
  77.             } 
  78.         }); 
  79.     }    /** 
  80.      * 在主線程中執(zhí)行的回調(diào) 
  81.      * @param response 
  82.      * @param callback 
  83.      * @param e 
  84.      */ 
  85.     private void callbackError(final Response response, final BaseCallback callback, final Exception e) { 
  86.         mHandler.post(new Runnable() {             
  87.             @Override 
  88.             public void run() { 
  89.                 callback.onError(response, response.code(), e); 
  90.             } 
  91.         }); 
  92.     }    /** 
  93.      * 在主線程中執(zhí)行的回調(diào) 
  94.      * @param request 
  95.      * @param callback 
  96.      * @param e 
  97.      */ 
  98.     private void callbackFailure(final Request request, final BaseCallback callback, final Exception e) { 
  99.         mHandler.post(new Runnable() {             
  100.             @Override 
  101.             public void run() { 
  102.                 callback.onFailure(request, e); 
  103.             } 
  104.         }); 
  105.     }    /** 
  106.      * 對(duì)外公開(kāi)的get方法 
  107.      * 
  108.      * @param url 
  109.      * @param callback 
  110.      */ 
  111.     public void get(String url, BaseCallback callback) { 
  112.         Request request = buildRequest(url, null, HttpMethodType.GET); 
  113.         request(request, callback); 
  114.     }    /** 
  115.      * 對(duì)外公開(kāi)的post方法 
  116.      * 
  117.      * @param url 
  118.      * @param params 
  119.      * @param callback 
  120.      */ 
  121.     public void post(String url, Map<String, String> params, BaseCallback callback) { 
  122.         Request request = buildRequest(url, params, HttpMethodType.POST); 
  123.         request(request, callback); 
  124.     }    /** 
  125.      * 構(gòu)建請(qǐng)求對(duì)象 
  126.      * 
  127.      * @param url 
  128.      * @param params 
  129.      * @param type 
  130.      * @return 
  131.      */ 
  132.     private Request buildRequest(String url, Map<String, String> params, HttpMethodType type) { 
  133.         Request.Builder builder = new Request.Builder(); 
  134.         builder.url(url);         
  135.             if (type == HttpMethodType.GET) { 
  136.             builder.get(); 
  137.         } else if (type == HttpMethodType.POST) { 
  138.             builder.post(buildRequestBody(params)); 
  139.         }        return builder.build(); 
  140.     }    /** 
  141.      * 通過(guò)Map的鍵值對(duì)構(gòu)建請(qǐng)求對(duì)象的body 
  142.      * 
  143.      * @param params 
  144.      * @return 
  145.      */ 
  146.     private RequestBody buildRequestBody(Map<String, String> params) { 
  147.  
  148.         FormEncodingBuilder builder = new FormEncodingBuilder();         
  149.             if (params != null) {             
  150.                 for (Map.Entry<String, String> entity : params.entrySet()) { 
  151.                 builder.add(entity.getKey(), entity.getValue()); 
  152.             } 
  153.         }        return builder.build(); 
  154.     }    /** 
  155.      * 這個(gè)枚舉用于指明是哪一種提交方式 
  156.      */ 
  157.     enum HttpMethodType { 
  158.         GET, 
  159.         POST 
  160.     } 
  161.  
  162.  

回調(diào)的封裝

  1. package com.nan.cnshop.http; 
  2.  
  3. import com.google.gson.internal.$Gson$Types; 
  4. import com.squareup.okhttp.Request; 
  5. import com.squareup.okhttp.Response; 
  6.  
  7. import java.lang.reflect.ParameterizedType; 
  8. import java.lang.reflect.Type;/** 
  9.  * 基本的回調(diào) 
  10.  */public abstract class BaseCallback<T> {    /** 
  11.      * type用于方便JSON的解析 
  12.      */ 
  13.     public Type mType;    /** 
  14.      * 把type轉(zhuǎn)換成對(duì)應(yīng)的類,這里不用看明白也行。 
  15.      * 
  16.      * @param subclass 
  17.      * @return 
  18.      */ 
  19.     static Type getSuperclassTypeParameter(Class<?> subclass) { 
  20.         Type superclass = subclass.getGenericSuperclass();         
  21.         if (superclass instanceof Class) {             
  22.             throw new RuntimeException("Missing type parameter."); 
  23.         } 
  24.         ParameterizedType parameterized = (ParameterizedType) superclass;         
  25.             return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]); 
  26.     }    /** 
  27.      * 構(gòu)造的時(shí)候獲得type的class 
  28.      */ 
  29.     public BaseCallback() { 
  30.         mType = getSuperclassTypeParameter(getClass()); 
  31.     }    /** 
  32.      * 請(qǐng)求之前調(diào)用 
  33.      */ 
  34.     public abstract void onRequestBefore();     
  35.      /** 
  36.      * 請(qǐng)求失敗調(diào)用(網(wǎng)絡(luò)問(wèn)題) 
  37.      * 
  38.      * @param request 
  39.      * @param e 
  40.      */ 
  41.     public abstract void onFailure(Request request, Exception e);     
  42.      /** 
  43.      * 請(qǐng)求成功而且沒(méi)有錯(cuò)誤的時(shí)候調(diào)用 
  44.      * 
  45.      * @param response 
  46.      * @param t 
  47.      */ 
  48.     public abstract void onSuccess(Response response, T t);     
  49.      /** 
  50.      * 請(qǐng)求成功但是有錯(cuò)誤的時(shí)候調(diào)用,例如Gson解析錯(cuò)誤等 
  51.      * 
  52.      * @param response 
  53.      * @param errorCode 
  54.      * @param e 
  55.      */ 
  56.     public abstract void onError(Response response, int errorCode, Exception e); 
  57.  
  58.  

OKHttp封裝之后的使用

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

  1. mHttpHelper=OkHttpHelper.getinstance(); 
  2. mHttpHelper.get(Constants.URL_BANNER, new BaseCallback<List<Banner>>() {     
  3.     @Override 
  4.     public void onRequestBefore() { 
  5.  
  6.     }    @Override 
  7.     public void onFailure(Request request, Exception e) { 
  8.  
  9.     }    @Override 
  10.     public void onSuccess(Response response, List<Banner> banners) { 
  11.         initBanners(banners); 
  12.     }    @Override 
  13.     public void onError(Response response, int errorCode, Exception e) { 
  14.  
  15.     } 
  16. });  

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

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

責(zé)任編輯:龐桂玉 來(lái)源: 安卓巴士Android開(kāi)發(fā)者門戶
相關(guān)推薦

2023-09-28 09:07:54

注解失效場(chǎng)景

2012-12-24 09:55:59

交換機(jī)網(wǎng)絡(luò)通信

2022-12-06 23:43:53

iOSCreateML應(yīng)用

2013-04-15 09:48:40

AndroidAVD錯(cuò)誤處理方法

2021-12-09 09:52:36

云原生安全工具云安全

2010-07-19 16:55:51

Telnet命令

2010-04-30 11:10:32

Oracle Sql

2018-07-30 08:20:39

編程語(yǔ)言Python集合

2010-04-23 09:51:12

Oracle工具

2023-07-17 06:57:16

2021-07-30 15:06:05

鴻蒙HarmonyOS應(yīng)用

2024-06-28 07:59:34

C#編程字段

2022-09-09 20:55:38

LinkerdKubernetes

2021-08-24 23:23:35

Python工具開(kāi)發(fā)

2023-03-01 14:32:31

redisIOEpoll

2011-07-28 15:11:42

組策略

2018-08-09 08:00:00

Linux命令內(nèi)存用量

2010-03-10 11:45:15

云計(jì)算

2011-12-29 16:18:14

API

2020-03-16 17:20:02

異常處理Spring Boot
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)