Android 一個改善的okHttp封裝庫

来源:http://www.cnblogs.com/upwgh/archive/2017/03/14/6548974.html
-Advertisement-
Play Games

之前寫了篇Android OkHttp完全解析 是時候來瞭解OkHttp了,其實主要是作為okhttp的普及文章,當然裡面也簡單封裝了工具類,沒想到關註和使用的人還挺多的,由於這股熱情,該工具類中的方法也是劇增,各種重載方法,以致於使用起來極不方便,實在慚愧。 於是,在這個周末,抽點時間對該工具類... ...


膜拜一下~

轉載請標明出處:
http://blog.csdn.net/lmj623565791/article/details/49734867
本文出自:【張鴻洋的博客】

一、概述

之前寫了篇Android OkHttp完全解析 是時候來瞭解OkHttp了,其實主要是作為okhttp的普及文章,當然裡面也簡單封裝了工具類,沒想到關註和使用的人還挺多的,由於這股熱情,該工具類中的方法也是劇增,各種重載方法,以致於使用起來極不方便,實在慚愧。

於是,在這個周末,抽點時間對該工具類,進行了重新的拆解與編寫,順便完善下功能,儘可能的提升其使用起來的方便性和易擴展性。

標題的改善,也是指的是對於我之前的代碼進行改善。

如果你對okhttp不瞭解,可以通過Android OkHttp完全解析 是時候來瞭解OkHttp了進行瞭解。

ok,那麼目前,該封裝庫志支持:

  • 一般的get請求
  • 一般的post請求
  • 基於Http的文件上傳
  • 文件下載
  • 上傳下載的進度回調
  • 載入圖片
  • 支持請求回調,直接返回對象、對象集合
  • 支持session的保持
  • 支持自簽名網站https的訪問,提供方法設置下證書就行
  • 支持取消某個請求

源碼地址:https://github.com/hongyangAndroid/okhttp-utils

引入:compile 'com.squareup.okhttp3:okhttp:3.3.1'

 

二、基本用法

 

目前基本的用法格式為:

OkHttpUtils
    .get()
    .url(url)
    .addParams("username", "hyman")
    .addParams("password", "123")
    .build()
    .execute(callback);

通過鏈式去根據自己的需要添加各種參數,最後調用execute(callback)進行執行,傳入callback則代表是非同步。如果單純的execute()則代表同步的方法調用。

可以看到,取消了之前一堆的get重載方法,參數也可以進行靈活的選擇了。

下麵簡單看一下,全部的用法:

(1)GET請求

String url = "http://www.csdn.net/";
OkHttpUtils
    .get()
    .url(url)
    .addParams("username", "hyman")
    .addParams("password", "123")
    .build()
    .execute(new StringCallback()
            {
                @Override
                public void onError(Request request, Exception e)
                {

                }

                @Override
                public void onResponse(String response)
                {

                }
            });

(2)POST請求

 OkHttpUtils
    .post()
    .url(url)
    .addParams("username", "hyman")
    .addParams("password", "123")
    .build()
    .execute(callback);

(3)Post String

OkHttpUtils
    .postString()
    .url(url)
    .content(new Gson().toJson(new User("zhy", "123")))
    .build()
    .execute(new MyStringCallback()); 

將string作為請求體傳入到服務端,例如json字元串。

(4)Post File

OkHttpUtils
    .postFile()
    .url(url)
    .file(file)
    .build()
    .execute(new MyStringCallback());

將file作為請求體傳入到服務端.

(5)基於POST的文件上傳(類似web上的表單)

OkHttpUtils.post()//
    .addFile("mFile", "messenger_01.png", file)//
    .addFile("mFile", "test1.txt", file2)//
    .url(url)
    .params(params)//
    .headers(headers)//
    .build()//
    .execute(new MyStringCallback());

(6)下載文件

OkHttpUtils//
    .get()//
    .url(url)//
    .build()//
    .execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), "gson-2.2.1.jar")//
    {
        @Override
        public void inProgress(float progress)
        {
            mProgressBar.setProgress((int) (100 * progress));
        }

        @Override
        public void onError(Request request, Exception e)
        {
            Log.e(TAG, "onError :" + e.getMessage());
        }

        @Override
        public void onResponse(File file)
        {
            Log.e(TAG, "onResponse :" + file.getAbsolutePath());
        }
    });

(7)顯示圖片

OkHttpUtils
    .get()//
    .url(url)//
    .build()//
    .execute(new BitmapCallback()
    {
        @Override
        public void onError(Request request, Exception e)
        {
            mTv.setText("onError:" + e.getMessage());
        }

        @Override
        public void onResponse(Bitmap bitmap)
        {
            mImageView.setImageBitmap(bitmap);
        }
    });

哈,目前來看,清晰多了。

三、對於上傳下載的回調

new Callback<?>()
{
    //...
    @Override
    public void inProgress(float progress)
    {
       //use progress: 0 ~ 1
    }
}

對於傳入的callback有個inProgress方法,需要拿到進度直接覆寫該方法即可。

四、對於自動解析為實體類

目前去除了Gson的依賴,提供了自定義Callback的方式,讓用戶自己去解析返回的數據,目前提供了StringCallbackFileCallback,BitmapCallback 分別用於返回string,文件下載,載入圖片。

當然如果你希望解析為對象,你可以:

public abstract class UserCallback extends Callback<User>
{
    //非UI線程,支持任何耗時操作
    @Override
    public User parseNetworkResponse(Response response) throws IOException
    {
        String string = response.body().string();
        User user = new Gson().fromJson(string, User.class);
        return user;
    }
}

自己使用自己喜歡的Json解析庫完成即可。

解析成List<User>,則如下:

public abstract class ListUserCallback extends Callback<List<User>>
{
    @Override
    public List<User> parseNetworkResponse(Response response) throws IOException
    {
        String string = response.body().string();
        List<User> user = new Gson().fromJson(string, List.class);
        return user;
    }
}

五、對於https單向認證

非常簡單,拿到xxx.cert的證書。

然後調用

OkHttpUtils.getInstance()
        .setCertificates(inputstream);

建議使用方式,例如我的證書放在assets目錄:

/**
 * Created by zhy on 15/8/25.
 */
public class MyApplication extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();

        try
        {    
        OkHttpUtils
         .getInstance()
         .setCertificates(getAssets().open("aaa.cer"),
 getAssets().open("server.cer"));
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

即可。別忘了註冊Application。

註意:如果https網站為權威機構頒發的證書,不需要以上設置。自簽名的證書才需要。

六、配置

(1)全局配置

可以在Application中,通過:

OkHttpClient client = 
OkHttpUtils.getInstance().getOkHttpClient();

然後調用client的各種set方法。

例如:

client.setConnectTimeout(100000, TimeUnit.MILLISECONDS);

(2)為單個請求設置超時

比如涉及到文件的需要設置讀寫等待時間多一點。

 OkHttpUtils
    .get()//
    .url(url)//
    .tag(this)//
    .build()//
    .connTimeOut(20000)
    .readTimeOut(20000)
    .writeTimeOut(20000)
    .execute()

調用build()之後,可以隨即設置各種timeOut.

(3)取消單個請求

 RequestCall call = OkHttpUtils.get().url(url).build();
 call.cancel();

(4)根據tag取消請求

目前對於支持的方法都添加了最後一個參數Object tag,取消則通過OkHttpUtils.cancelTag(tag)執行。

例如:在Activity中,當Activity銷毀取消請求:

OkHttpUtils
    .get()//
    .url(url)//
    .tag(this)//
    .build()//

@Override
protected void onDestroy()
{
    super.onDestroy();
    //可以取消同一個tag的
    OkHttpUtils.cancelTag(this);//取消以Activity.this作為tag的請求
}

比如,當前Activity頁面所有的請求以Activity對象作為tag,可以在onDestory裡面統一取消。

七、淺談封裝

其實整個封裝的過程比較簡單,這裡簡單描述下,對於okhttp一個請求的流程大致是這樣的:

//創建okHttpClient對象
OkHttpClient mOkHttpClient = new OkHttpClient();
//創建一個Request
final Request request = new Request.Builder()
                .url("https://github.com/hongyangAndroid")
                .build();
//new call
Call call = mOkHttpClient.newCall(request); 
//請求加入調度
call.enqueue(new Callback()
{
    @Override
    public void onFailure(Request request, IOException e)
    {
    }

    @Override
    public void onResponse(final Response response) throws IOException
    {
            //String htmlStr =  response.body().string();
    }
});  

其中主要的差異,其實就是request的構建過程。

我對Request抽象了一個類:OkHttpRequest

public abstract class OkHttpRequest
{
    protected RequestBody requestBody;
    protected Request request;

    protected String url;
    protected String tag;
    protected Map<String, String> params;
    protected Map<String, String> headers;

    protected OkHttpRequest(String url, String tag,
                            Map<String, String> params, Map<String, String> headers)
    {
        this.url = url;
        this.tag = tag;
        this.params = params;
        this.headers = headers;
    }

    protected abstract Request buildRequest();
    protected abstract RequestBody buildRequestBody();

    protected void prepareInvoked(ResultCallback callback)
    {
        requestBody = buildRequestBody();
        requestBody = wrapRequestBody(requestBody, callback);
        request = buildRequest();
    }

    protected RequestBody wrapRequestBody(RequestBody requestBody, final ResultCallback callback)
    {
        return requestBody;
    }


    public void invokeAsyn(ResultCallback callback)
    {
        prepareInvoked(callback);
        mOkHttpClientManager.execute(request, callback);
    }


     // other common methods
 }   

一個request的構建呢,我分三個步驟:buildRequestBody , wrapRequestBody ,buildRequest這樣的次序,當以上三個方法沒有問題時,我們就拿到了request,然後執行即可。

但是對於不同的請求,requestBody以及request的構建過程是不同的,所以大家可以看到buildRequestBody ,buildRequest為抽象的方法,也就是不同的請求類,比如OkHttpGetRequestOkHttpPostRequest等需要自己去構建自己的request。

對於wrapRequestBody方法呢,可以看到它預設基本屬於空實現,主要是因為並非所有的請求類都需要覆寫它,只有上傳的時候呢,需要回調進度,需要對requestBody進行包裝,所以這個方法類似於一個鉤子。

其實這個過程有點類似模板方法模式,有興趣可以看看一個短篇介紹設計模式 模版方法模式 展現程式員的一天 .

對於更加詳細的用法,可以查看github上面的readme,以及demo,目前demo包含:

對於上傳文件的兩個按鈕,需要自己搭建伺服器,其他的按鈕可以直接測試

最後,由於本人水平有限,以及時間比較倉促~~發現問題,歡迎提issue,我會抽時間解決。 have a nice day ~

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 繼續做仿造著別人的第二個 1.首先下載 一些字體 網上搜索 "造字工房" 2.把下載的相應字體文件放到工程之中,就Ok了 不多說 效果如下 可以下麵這個方法 檢索項目裡面所有的字體 代碼如下 ...
  • 環境: react native: 0.41.2 react native image picker: 0.26.2 xcode 8.2.1 iphone 6 根據官方教程( "https://github.com/marcshilling/react native image picker" )寫 ...
  • 最近公司項目不是很忙,偶然間看到編程語言排行榜,看到swift 已經排到前10了,然OC排名也越來越後了,感覺要上車了,雖然現在項目都是用OC寫的,但是swift是一種趨勢。在網上看到“自學 iOS - 三十天三十個 Swift 項目” 這篇博客,我也想自己在閑暇之餘學習下swift,在看了2天的s ...
  • 1.如何使edittext點擊後全選裡面的內容啊? 2.記一次EditText設置預設選中setSelection的一個bug 需求:在重命名的時候,要預設選中文件的尾碼之前的名字; 代碼如下: 但是發現有的文件重命名的時候app崩潰,報錯如下:java.lang.IndexOutOfBoundsE ...
  • Environment.getExternalStorageDirectory()是Android 2.x時代的產物,那時Android主流設備只有很小的內置存儲器,然後都會外置一張sd卡,那時這個方法返回的就是外置sd卡的根路徑。但隨著Android進入4.x時代,大部分Android設備都已經內 ...
  • 一、簡介 Vitamio能夠流暢播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常見格式的視頻,還可以在Android 與 iOS 上跨平臺支持 MMS, RTSP, RTMP, HLS(m3u8) 等常見的多種視頻流媒體協議,包括點播與直播。 使用Vitamio框架主 ...
  • 1. 使用流程 2. 常用屬性   numColumns:指定顯示的列數,若不指定該屬性,則預設所有項排成1列。   verticalSpacing:行距。   horizontalSpacing:列距,若指定了numColumns,則按照 ...
  • 單例模式是非常常見的設計模式,其含義也很簡單,一個類給外部提供一個唯一的實例。下文所有的代碼均在 "github" 源碼整個項目不僅僅有設計模式,還有其他JavaSE知識點,歡迎Star,Fork 單例模式的UML圖 單例模式的關鍵點 通過上面的UML圖,我們可以看出單例模式的特點如下: 1. 構造 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...