開源項目OkHttpPlus——OkHttp封裝庫沼本,支持GET、POST锭沟、UI線程回調(diào)抽兆、JSON格式解析、鏈?zhǔn)秸{(diào)用族淮、小文件上傳下載及進(jìn)度監(jiān)聽

OkHttpPlus介紹

項目地址:https://github.com/ZhaoKaiQiang/OkHttpPlus

主要功能:OkHttp封裝辫红,支持GET、POST祝辣、UI線程回調(diào)厉熟、JSON格式解析、鏈?zhǔn)秸{(diào)用较幌、小文件上傳下載及進(jìn)度監(jiān)聽等功能

為什么要寫這么一個庫呢揍瑟?

首先,是因為OkHttp在4.4之后已經(jīng)作為底層的Http實現(xiàn)了乍炉,所以O(shè)kHttp這個庫很強大绢片,值得我們學(xué)習(xí)。

其次岛琼,在我看來底循,OkHttp使用起來不如Volley方便,OkHttp的回調(diào)都是在工作線程槐瑞,所以如果在回調(diào)里面操作View的話熙涤,需要自己轉(zhuǎn)換到UI線程,非常繁瑣困檩,所以需要封裝祠挫。也有將OkHttp作為Volley底層Http實現(xiàn)的用法,發(fā)送請求悼沿、維護(hù)請求隊列用的是Volley等舔,實際的Http請求用的是OkHttp。

關(guān)于Volley和oOkHttp結(jié)合的Demo請戳煎蛋項目

如何使用

初始化

你可以在Application里面完成初始化糟趾,因為對OkHttp的封裝主要使用的是代理設(shè)計模式慌植,使用OkHttpProxy.getInstance()可以獲取到單例客戶端甚牲,你可以像沒封裝之前一樣,設(shè)置任意的參數(shù)蝶柿,比如下面就設(shè)置超時時間和忽略HTTPS認(rèn)證丈钙。

public class OkApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        OkHttpClient okHttpClient = OkHttpProxy.getInstance();
        okHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
        okHttpClient.setReadTimeout(15, TimeUnit.SECONDS);
        okHttpClient.setWriteTimeout(15, TimeUnit.SECONDS);

        //ignore HTTPS Authentication
        okHttpClient.setHostnameVerifier(new MyHostnameVerifier());
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom());
            okHttpClient.setSslSocketFactory(sc.getSocketFactory());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
    }
}

Get方法

你大多數(shù)情況下是和OkHttpProxy這個代理類打交道,而且OkHttpPlus支持鏈?zhǔn)秸{(diào)用交汤,內(nèi)部采用Builder設(shè)計模式雏赦,所以你可以像下面這樣使用

 OkHttpProxy.get()
                .url(URL_USER)
                .tag(this)
                .execute(new OkCallback<User>(new OkJsonParser<User>() {
                }) {
                    @Override
                    public void onSuccess(int code, User user) {
                        tv_response.setText(user.toString());
                    }

                    @Override
                    public void onFailure(Throwable e) {
                        tv_response.setText(e.getMessage());
                    }
                });

為了支持返回值解析,這里我采用了泛型蜻展,在OkCallback的構(gòu)造函數(shù)中,你需要傳入一個解析器邀摆,OkHttpPlus內(nèi)部支持5種解析器纵顾,這可以解決你大部分的需求

  • OkBaseParser,所有解析器的基類栋盹,不可直接使用
  • OkBaseJsonParser施逾,所有JSON解析器的基類,你可以繼承它來定義自己的JSON解析
  • OkJsonParser例获,JSON解析器汉额,支持JSONObject和JSONArray的解析,默認(rèn)使用GSON作為解析器
  • OkTextParser榨汤,String解析器蠕搜,支持將結(jié)果以String方式輸出
  • OkFileParser,文件解析器收壕,支持將結(jié)果保存為文件妓灌,你可以用來下載文件,但是不支持較大文件下載

所以如果你想獲取一個JSONArray蜜宪,你可以像下面這樣

 OkHttpProxy.get()
                .url(URL_USER)
                .tag(this)
                .execute(new OkCallback<List<User>>(new OkJsonParser<List<User>>() {
                }) {
                    @Override
                    public void onSuccess(int code, List<User> users) {
                        tv_response.setText(users.toString());
                    }

                    @Override
                    public void onFailure(Throwable e) {
                        tv_response.setText(e.getMessage());
                    }
                });

你如果想獲取String數(shù)據(jù)虫埂,你可以這樣

  OkHttpProxy.get()
                .url(URL_BAIDU)
                .tag(this)
                .execute(new OkCallback<String>(new OkTextParser()) {
                    @Override
                    public void onSuccess(int code, String s) {
                        tv_response.setText(s);
                    }

                    @Override
                    public void onFailure(Throwable e) {
                        tv_response.setText(e.getMessage());
                    }
                });

當(dāng)然,如果你想自定義一個解析器圃验,也是完全可以的掉伏。

OkHttpPlus的解析器部分使用的是策略設(shè)計模式,所以你可以像下面這樣自定義一個解析策略澳窑,完成結(jié)果的解析

public class JokeParser<T> extends OkJsonParser<T> {

    @Nullable
    @Override
    public T parse(Response response) throws IOException {
        String jsonStr = response.body().string();
        try {
            jsonStr = new JSONObject(jsonStr).getJSONArray("comments").toString();
            return mGson.fromJson(jsonStr, new TypeToken<ArrayList<Joke>>() {
            }.getType());
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
    }
}

然后就可以將返回結(jié)果解析為ArrayList<Joke>了

  OkHttpProxy.get()
                .url(Joke.getRequestUrl(1))
                .tag(this).execute(new OkCallback<List<Joke>>(new JokeParser()) {
            @Override
            public void onSuccess(int code, List<Joke> jokes) {
                tv_response.setText(jokes.toString());
            }

            @Override
            public void onFailure(Throwable e) {
                tv_response.setText(e.getMessage());
            }
        });

Post方法

Post的方法與Get方法使用類似斧散,你可以像下面這樣發(fā)送POST請求,并添加Header和Params摊聋。

 OkHttpProxy
                .post()
                .url(URL_USERS)
                .tag(this)
                .addParams("name", "zhaokaiqiang")
                .addHeader("header", "okhttp")
                .execute(new OkCallback<ArrayList<User>>(new OkJsonParser<ArrayList<User>>() {
                }) {
                    @Override
                    public void onSuccess(int code, ArrayList<User> users) {
                        tv_response.setText(users.toString());
                    }

                    @Override
                    public void onFailure(Throwable e) {
                        tv_response.setText(e.getMessage());
                    }
                });

你可能注意到了颅湘,在發(fā)送每個請求的時候,我都調(diào)用了tag()方法栗精,所以你可以在不需要的時候闯参,將請求取消掉瞻鹏。

@Override
    protected void onDestroy() {
        super.onDestroy();
        OkHttpProxy.cancel(this);
    }

下載

你可以像下面這樣下載一個文件,但是由于下載的內(nèi)容都在內(nèi)存中鹿寨,所以不支持大文件下載新博,否則會OOM

 String desFileDir = Environment.getExternalStorageDirectory().getAbsolutePath();
        OkHttpProxy.download(URL_DOWMLOAD, new DownloadListener(desFileDir, "json.jar") {

            @Override
            public void onUIProgress(Progress progress) {
                //當(dāng)下載資源長度不可知時,progress.getTotalBytes()為-1脚草,此時不能顯示下載進(jìn)度
                int pro = (int) (progress.getCurrentBytes() / progress.getTotalBytes() * 100);
                if (pro > 0) {
                    pb.setProgress(pro);
                }
                KLog.d("pro = " + pro + " getCurrentBytes = " + progress.getCurrentBytes() + " getTotalBytes = " + progress.getTotalBytes());
            }

            @Override
            public void onSuccess(File file) {
                tv_response.setText(file.getAbsolutePath());
            }

            @Override
            public void onFailure(Exception e) {
                tv_response.setText(e.getMessage());
            }
        });
    }

上傳

OkHttpPlus也支持小文件上傳赫悄,我這里測試使用的是七牛的上傳API,Token是有期限的馏慨,所以你需要在下面網(wǎng)址自己生成測試

 /**
     * 采用七牛上傳接口埂淮,Token有效期為12小時,若Token無效写隶,請在下面自行獲取
     * Token生成網(wǎng)址 http://jsfiddle.net/gh/get/extjs/4.2/icattlecoder/jsfiddle/tree/master/uptoken
     * <p/>
     * AK = IUy4JnOZHP6o-rx9QsGLf9jMTAKfRkL07gNssIDA
     * CK = DkfA7gPTNy1k4HWnQynra3qAZhrzp-wmSs15vub6
     * BUCKE_NAME = zhaokaiqiang
     */
    public void uploadFile(View view) {

        File file = new File(Environment.getExternalStorageDirectory(), "jiandan02.jpg");
        if (!file.exists()) {
            Toast.makeText(MainActivity.this, "文件不存在倔撞,請修改文件路徑", Toast.LENGTH_SHORT).show();
            return;
        }

        Map<String, String> param = new HashMap<>();
        param.put("token", TOKEN);
        Pair<String, File> pair = new Pair("file", file);

        OkHttpProxy
                .upload()
                .url(URL_UPLOAD)
                .file(pair)
                .setParams(param)
                .setWriteTimeOut(20)
                .start(new UploadListener() {
                    @Override
                    public void onSuccess(Response response) {
                        tv_response.setText("isSuccessful = " + response.isSuccessful() + "\n" + "code = " + response.code());
                    }

                    @Override
                    public void onFailure(Exception e) {
                        tv_response.setText(e.getMessage());
                    }

                    @Override
                    public void onUIProgress(Progress progress) {
                        int pro = (int) ((progress.getCurrentBytes() + 0.0) / progress.getTotalBytes() * 100);
                        if (pro > 0) {
                            pb.setProgress(pro);
                        }
                        KLog.d("pro = " + pro + " getCurrentBytes = " + progress.getCurrentBytes() + " getTotalBytes = " + progress.getTotalBytes());
                    }
                });
    }

靈感來源

本項目的靈感和部分代碼來自于下面兩個開源項目,謝謝他們的分享精神


尊重原創(chuàng)慕趴,轉(zhuǎn)載請注明:From 凱子哥 侵權(quán)必究痪蝇!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市冕房,隨后出現(xiàn)的幾起案子躏啰,更是在濱河造成了極大的恐慌,老刑警劉巖耙册,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件给僵,死亡現(xiàn)場離奇詭異,居然都是意外死亡详拙,警方通過查閱死者的電腦和手機想际,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來溪厘,“玉大人胡本,你說我怎么就攤上這事』” “怎么了侧甫?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹋宦。 經(jīng)常有香客問我披粟,道長,這世上最難降的妖魔是什么冷冗? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任守屉,我火速辦了婚禮,結(jié)果婚禮上蒿辙,老公的妹妹穿的比我還像新娘拇泛。我一直安慰自己滨巴,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布俺叭。 她就那樣靜靜地躺著恭取,像睡著了一般。 火紅的嫁衣襯著肌膚如雪熄守。 梳的紋絲不亂的頭發(fā)上蜈垮,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機與錄音裕照,去河邊找鬼攒发。 笑死,一個胖子當(dāng)著我的面吹牛晋南,可吹牛的內(nèi)容都是我干的惠猿。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼搬俊,長吁一口氣:“原來是場噩夢啊……” “哼紊扬!你這毒婦竟也來了蜒茄?” 一聲冷哼從身側(cè)響起唉擂,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎檀葛,沒想到半個月后玩祟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡屿聋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年空扎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片润讥。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡转锈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出楚殿,到底是詐尸還是另有隱情撮慨,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布脆粥,位于F島的核電站砌溺,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏变隔。R本人自食惡果不足惜规伐,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匣缘。 院中可真熱鬧猖闪,春花似錦鲜棠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至检柬,卻和暖如春献联,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背何址。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工里逆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人用爪。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓原押,卻偏偏與公主長得像,于是被迫代替她去往敵國和親偎血。 傳聞我的和親對象是個殘疾皇子诸衔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,573評論 2 353

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