Android小白之OkHttp的使用介紹

前言

在Android開發(fā)中,OKhttp已經(jīng)成為眼下最火的http請(qǐng)求框架划址,那么OKhttp有什么過人之處呢蛀骇?接下來就對(duì)OKhttp的學(xué)習(xí)進(jìn)行總結(jié)和泌。

一. OKhttp優(yōu)勢(shì):

OkHttp 是一個(gè)高效的 http 客戶端评汰,特點(diǎn)如下:

  • 支持 http2(基于SPDY協(xié)議) 協(xié)議纷捞,對(duì)同一個(gè)主機(jī)的所有請(qǐng)求允許使用同一個(gè) socket;
  • 如果 http2 不可用被去,使用鏈接池技術(shù)來降低了請(qǐng)求響應(yīng)的延遲主儡;
  • 使用透明的 gzip 壓縮減少了數(shù)據(jù)流量;
  • 使用網(wǎng)絡(luò)緩存避免了重復(fù)的網(wǎng)絡(luò)請(qǐng)求惨缆。

拓展--SPDY協(xié)議:SPDY協(xié)議是Google提出的基于傳輸控制協(xié)議(TCP)的應(yīng)用層協(xié)議糜值,通過壓縮、多路復(fù)用和優(yōu)先級(jí)來縮短加載時(shí)間踪央。該協(xié)議是一種更加快速的內(nèi)容傳輸協(xié)議臀玄。SPDY協(xié)議相比于HTTP的優(yōu)勢(shì)在于:

  • 復(fù)用連接瓢阴,可在一個(gè)TCP連接上傳送多個(gè)資源畅蹂。應(yīng)對(duì)了TCP慢啟動(dòng)的特性。
  • 請(qǐng)求分優(yōu)先級(jí)荣恐,重要的資源優(yōu)先傳送液斜。
  • HTTP頭部數(shù)據(jù)也被壓縮累贤,省流量。
  • 服務(wù)器端可主動(dòng)連接客戶端來推送資源(Server Push)少漆。

二. OKhttp的主要功能:

  • 發(fā)送get臼膏,post請(qǐng)求;
  • 文件的上傳示损,下載渗磅;
  • 加載圖片(內(nèi)部會(huì)根據(jù)圖片的大小進(jìn)行壓縮);
  • 支持請(qǐng)求回調(diào)检访,直接返回對(duì)象或者對(duì)象集合始鱼;
  • 支持session的保持。

三. OKhttp的基本使用:

OKhttp使用之前需要添加依賴:

compile "com.squareup.okhttp:okhttp:3.2.0"

清單文件中添加網(wǎng)絡(luò)訪問權(quán)限:

<uses-permission android:name="android.permission.INTERNET"/>

1. get請(qǐng)求和post請(qǐng)求的區(qū)別:

  • get是從服務(wù)器上獲取數(shù)據(jù)脆贵,post是向服務(wù)器上傳輸數(shù)據(jù)医清。
  • get是把參數(shù)數(shù)據(jù)隊(duì)列加到提交表單的ACTION屬性所指的URL中,值和表單內(nèi)各個(gè)字段一一對(duì)應(yīng)卖氨,在URL中可以看到会烙。post是通過HTTP post機(jī)制,將表單內(nèi)各個(gè)字段與其內(nèi)容放置在HTML HEADER內(nèi)一起傳送到ACTION屬性所指的URL地址筒捺。用戶看不到這個(gè)過程柏腻。
  • 對(duì)于get方式,服務(wù)器端用Request.QueryString獲取變量的值焙矛,對(duì)于post方式葫盼,服務(wù)器端用Request.Form獲取提交的數(shù)據(jù)。
  • get傳送的數(shù)據(jù)量較小村斟,不能大于2KB贫导。post傳送的數(shù)據(jù)量較大,一般被默認(rèn)為不受限制蟆盹。但理論上孩灯,IIS4中最大量為80KB,IIS5中為100KB逾滥。
  • get安全性非常低峰档,post安全性較高。但是執(zhí)行效率卻比Post方法好寨昙。
  • get可以被瀏覽器緩存讥巡,post不可以。
  • get請(qǐng)求是安全的舔哪,post不安全欢顷。
  • 項(xiàng)目開發(fā)中,當(dāng)涉及到參數(shù)的安全問題或者參數(shù)比較大的時(shí)候捉蚤,應(yīng)該使用Post請(qǐng)求方式(例如:登錄抬驴,注冊(cè)炼七,上傳,支付布持,下單)豌拙;如果是相對(duì)簡(jiǎn)單的查詢類接口可以使用Get請(qǐng)求方式(例如:獲取圖片,獲取文章詳情)题暖。

2. 同步/異步發(fā)送get請(qǐng)求:

(1) 創(chuàng)建OkHttpClient對(duì)象:

OkHttpClient okHttpClient = new OkHttpClient();     

(2) 使用Request.Builder構(gòu)建請(qǐng)求對(duì)象:

Request類封裝了請(qǐng)求報(bào)文信息:請(qǐng)求的Url地址按傅、請(qǐng)求的方法(如GET、POST等)胧卤、各種請(qǐng)求頭(如Content-Type逞敷、Cookie)以及可選的請(qǐng)求體。一般通過內(nèi)部類Request.Builder的鏈?zhǔn)秸{(diào)用生成Request對(duì)象灌侣。

Request request = new Request.Builder()
            .url(URL)
            .build();

(3) 創(chuàng)建一個(gè)call對(duì)象推捐,對(duì)象是response,發(fā)送請(qǐng)求

Call代表了一個(gè)實(shí)際的HTTP請(qǐng)求侧啼,它是連接Request和Response的橋梁牛柒,通過Request對(duì)象的newCall()方法可以得到一個(gè)Call對(duì)象。Call對(duì)象既支持同步獲取數(shù)據(jù)痊乾,也可以異步獲取數(shù)據(jù)皮壁。

  • 執(zhí)行Call對(duì)象的execute()方法,會(huì)阻塞當(dāng)前線程去獲取數(shù)據(jù)哪审,該方法返回一個(gè)Response對(duì)象蛾魄。

  • 執(zhí)行Call對(duì)象的enqueue()方法,不會(huì)阻塞當(dāng)前線程湿滓,該方法接收一個(gè)Callback對(duì)象滴须,當(dāng)異步獲取到數(shù)據(jù)之后,會(huì)回調(diào)執(zhí)行Callback對(duì)象的相應(yīng)方法叽奥。如果請(qǐng)求成功扔水,則執(zhí)行Callback對(duì)象的onResponse方法,并將Response對(duì)象傳入該方法中朝氓;如果請(qǐng)求失敗魔市,則執(zhí)行Callback對(duì)象的onFailure方法。

      Call call = okHttpClient.newCall(request);
    

(4) 通過調(diào)用execute()發(fā)送同步請(qǐng)求,調(diào)用enqueue()發(fā)送異步請(qǐng)求,獲取到response對(duì)象

Response類封裝了響應(yīng)報(bào)文信息:狀態(tài)嗎(200赵哲、404等)待德、響應(yīng)頭(Content-Type、Server等)以及可選的響應(yīng)體枫夺〗埽可以通過Call對(duì)象的execute()方法獲得Response對(duì)象,異步回調(diào)執(zhí)行Callback對(duì)象的onResponse方法時(shí)也可以獲取Response對(duì)象。

//調(diào)用execute()發(fā)送同步請(qǐng)求
try {
     Response response = call.execute();
    //判斷請(qǐng)求是否成功
    if(response.isSuccessful()) {
        Log.i("TAG",response.body().string());
        response.body().close();
    }
    //關(guān)閉body
    response.body().close();
    } catch (IOException e) {
        e.printStackTrace();
    }

//通過調(diào)用enqueue()發(fā)送異步請(qǐng)求,異步請(qǐng)求開啟了新的線程執(zhí)行網(wǎng)絡(luò)請(qǐng)求
call.enqueue(new Callback() {
    @Override
    public void onFailure(Request request, IOException e) {
        //請(qǐng)求失敗的回調(diào)方法
    }

    @Override
    public void onResponse(Response response) throws IOException {   
        //請(qǐng)求成功的回調(diào)方法
        String result = response.body().string();
        Log.i("TAG",result);
        //關(guān)閉body
        response.body().close();
    }
});

3. 同步/異步發(fā)送post請(qǐng)求:

public static final MediaType JSON = MediaType
        .parse("application/json; charset=utf-8");
public static final String json = "{android: hello world!}";

/**
 * 同步發(fā)送post請(qǐng)求提交json數(shù)據(jù)
 */

OkHttpClient okhttpClient = new OkHttpClient();

//創(chuàng)建一個(gè)RequestBody對(duì)象(參數(shù)1:參數(shù)類型涧偷,參數(shù)2:傳輸?shù)膉son串)
RequestBody requestBody = RequestBody.create(JSON,json);

//創(chuàng)建一個(gè)請(qǐng)求對(duì)象
Request request = new Request.Builder()
        .url(URL)
        .post(requestBody)
        .build();

//發(fā)送同步請(qǐng)求,獲取響應(yīng)對(duì)象
Call call = okhttpClient.newCall(request);
try {
    Response response = call.execute();
    //判斷請(qǐng)求是否成功
    if(response.isSuccessful()) {
        Log.i("TAG",response.body().string());
        response.body().close();
    }
} catch (IOException e) {
    e.printStackTrace();
}

/**
 * 異步發(fā)送post請(qǐng)求提交鍵值對(duì)
 */

OkHttpClient okHttpClient = new OkHttpClient();
//創(chuàng)建一個(gè)請(qǐng)求體
RequestBody requestBody = new FormEncodingBuilder()
        .add("name","張三")
        .add("age","24")
        .add("sex","男")
        .build();
//創(chuàng)建一個(gè)請(qǐng)求對(duì)象
Request request = new Request.Builder()
        .url(URL)
        .post(requestBody)
        .build();

//發(fā)送異步請(qǐng)求毙死,獲取響應(yīng)對(duì)象
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
    @Override
    public void onFailure(Request request, IOException e) {
        
    }

    @Override
    public void onResponse(Response response) throws IOException {
        //判斷請(qǐng)求是否成功
        if(response.isSuccessful()) {
            Log.i("TAG",response.body().string());
            response.body().close();
        }
    }
});

OkHttp的簡(jiǎn)單封裝 :

在項(xiàng)目中使用okhttp作為網(wǎng)絡(luò)訪問框架的時(shí)候燎潮,還是要對(duì)其封裝使用的,下面就簡(jiǎn)單的封裝一下:

public class OkHttpManager {

    public static OkHttpManager instence;
    private OkHttpClient mOkHttpClient;
    private Handler okHandler;

    private OkHttpManager() {
        //聲明Handler對(duì)指定為主線程looper,確保執(zhí)行線程在主線程中扼倘。
        okHandler = new Handler(Looper.getMainLooper());

        //指定超時(shí)時(shí)間等參數(shù)
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .connectTimeout(15, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS);
        mOkHttpClient = builder.build();
    }

    /**
     * 獲取當(dāng)前的實(shí)例對(duì)象确封,確保唯一性
     */
    public static OkHttpManager getInstence() {
        if (instence == null) {
            synchronized (OkHttpManager.class) {
                if (instence == null) {
                    instence = new OkHttpManager();
                }
            }
        }
        return instence;
    }

    /**
     * 發(fā)送get請(qǐng)求
     *
     * @param url
     * @param resultCallback
     */
    public void getNet(String url, ResultCallback resultCallback) {
        Request request = new Request.Builder()
                .url(url)  //接口地址
                .method("GET", null)  //默認(rèn)的也是GET,可以不設(shè)置
                .build();
        dealNet(request,resultCallback);
    }

    /**
     * 發(fā)送post請(qǐng)求
     *
     * @param url
     * @param resultCallback
     * @param param          傳入數(shù)量不定的參數(shù)
     */
    public void postNet(String url, ResultCallback resultCallback, Param... param) {
        if (param == null) {
            param = new Param[0];
        }
        FormBody.Builder frombody = new FormBody.Builder();
        for (Param p : param) {
            frombody.add(p.key, p.value);
        }
        RequestBody requestBody = frombody.build();
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)  //傳入構(gòu)建好的參數(shù)
                .build();

        dealNet(request,resultCallback);
    }

    /**
     * 網(wǎng)絡(luò)請(qǐng)求
     *
     * @param request        請(qǐng)求
     * @param resultCallback 自定義的監(jiān)聽回調(diào)
     */
    public void dealNet(final Request request, final ResultCallback resultCallback) {
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, final IOException e) {
                okHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //請(qǐng)求失敗的時(shí)候執(zhí)行的方法
                        resultCallback.onFailed(request, e);
                    }
                });
            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                String str = "";
                try {
                    str = response.body().string();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                final String finalStr = str;
                Log.i("OkHttpManager", "onResponse" + finalStr);
                okHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //請(qǐng)求成功的時(shí)候執(zhí)行的方法
                        resultCallback.onSuccess(finalStr);
                    }
                });
            }
        });
    }

    /**
     * 自定義監(jiān)聽回調(diào)
     */
    public static abstract class ResultCallback {
        public abstract void onFailed(Request request, IOException e);

        public abstract void onSuccess(String response);
    }

    /**
     * 參數(shù)封裝類
     */
    public static class Param {
        String key;
        String value;

        public Param() {
        }

        public Param(String key, String value) {
            this.key = key;
            this.value = value;
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市再菊,隨后出現(xiàn)的幾起案子爪喘,更是在濱河造成了極大的恐慌,老刑警劉巖纠拔,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秉剑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡稠诲,警方通過查閱死者的電腦和手機(jī)侦鹏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來臀叙,“玉大人略水,你說我怎么就攤上這事∪坝” “怎么了渊涝?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)床嫌。 經(jīng)常有香客問我跨释,道長(zhǎng),這世上最難降的妖魔是什么厌处? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任煤傍,我火速辦了婚禮,結(jié)果婚禮上嘱蛋,老公的妹妹穿的比我還像新娘蚯姆。我一直安慰自己,他們只是感情好洒敏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布龄恋。 她就那樣靜靜地躺著,像睡著了一般凶伙。 火紅的嫁衣襯著肌膚如雪郭毕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天函荣,我揣著相機(jī)與錄音显押,去河邊找鬼扳肛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛乘碑,可吹牛的內(nèi)容都是我干的挖息。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼兽肤,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼套腹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起资铡,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤电禀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后笤休,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尖飞,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年店雅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了葫松。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡底洗,死狀恐怖腋么,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情亥揖,我是刑警寧澤珊擂,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站费变,受9級(jí)特大地震影響摧扇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挚歧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一扛稽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧滑负,春花似錦在张、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至痴鳄,卻和暖如春瘟斜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工螺句, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虽惭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓蛇尚,卻偏偏與公主長(zhǎng)得像芽唇,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子佣蓉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)亲雪,斷路器勇凭,智...
    卡卡羅2017閱讀 134,651評(píng)論 18 139
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,958評(píng)論 6 13
  • 參考Android網(wǎng)絡(luò)請(qǐng)求心路歷程Android Http接地氣網(wǎng)絡(luò)請(qǐng)求(HttpURLConnection) 一...
    合肥黑閱讀 21,274評(píng)論 7 63
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,072評(píng)論 25 707
  • 鷹嘴豆是一種高營(yíng)養(yǎng)價(jià)值的食用豆, 富含多種植物蛋白和氨基酸、維生素义辕、粗纖維及鈣虾标、鎂、鐵等成份, 其中粗蛋白含量高達(dá)...
    cuijianqd閱讀 268評(píng)論 0 1