天天看點

Android 一個改善的okHttp封裝庫1. 概述2. 基本用法3. 對于上傳下載下傳的回調4. 對于自動解析為實體類5. 對于https單向認證6. 配置7. 淺談封裝

http://blog.csdn.net/lmj623565791/article/details/49734867; 本文出自:【張鴻洋的部落格】

1. 概述

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

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

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

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

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

  • 一般的get請求
  • 一般的post請求
  • 基于Http的檔案上傳
  • 檔案下載下傳
  • 上傳下載下傳的進度回調
  • 加載圖檔
  • 支援請求回調,直接傳回對象、對象集合
  • 支援session的保持
  • 支援自簽名網站https的通路,提供方法設定下證書就行
  • 支援取消某個請求

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

引入:

  • Android Studio

使用前,對于Android Studio的使用者,可以選擇添加:

compile project(':okhttputils')11
           

或者

  • Eclipse 自行copy源碼。

2. 基本用法

目前基本的用法格式為:

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

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

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

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

2.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.2 POST請求

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

           

2.3 Post String

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

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

2.4 Post File

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

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

2.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());
           

2.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) ( * 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());
        }
    });
           

2.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);
        }
    });
           

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

3. 對于上傳下載下傳的回調

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

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

4. 對于自動解析為實體類

目前去除了Gson的依賴,提供了自定義Callback的方式,讓使用者自己去解析傳回的資料,目前提供了

StringCallback

FileCallback

,

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;
    }


}
           

5. 對于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網站為權威機構頒發的證書,不需要以上設定。自簽名的證書才需要。

6. 配置

6.1 全局配置

可以在Application中,通過:

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

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

client.setConnectTimeout(, TimeUnit.MILLISECONDS);
           

6.2 為單個請求設定逾時

比如涉及到檔案的需要設定讀寫等待時間多一點。

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

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

6.3 取消單個請求

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

6.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裡面統一取消。

7. 淺談封裝

其實整個封裝的過程比較簡單,這裡簡單描述下,對于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

為抽象的方法,也就是不同的請求類,比如

OkHttpGetRequest

OkHttpPostRequest

等需要自己去建構自己的request。

對于

wrapRequestBody

方法呢,可以看到它預設基本屬于空實作,主要是因為并非所有的請求類都需要複寫它,隻有上傳的時候呢,需要回調進度,需要對requestBody進行包裝,是以這個方法類似于一個鈎子。

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

對于更加詳細的用法,可以檢視github上面的readme,以及demo,目前demo包含:

Android 一個改善的okHttp封裝庫1. 概述2. 基本用法3. 對于上傳下載下傳的回調4. 對于自動解析為實體類5. 對于https單向認證6. 配置7. 淺談封裝

對于上傳檔案的兩個按鈕,需要自己搭建伺服器,其他的按鈕可以直接測試。

最後,由于本人水準有限,以及時間比較倉促~~發現問題,歡迎提issue,我會抽時間解決