基於鴻洋okhttp封裝工具類okhttputils 返回數據回調封裝

簡介

okhttputils 是csdn 鴻洋大神基於okhttp網絡請求進行的二次封裝

基本請求格式如下

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

工具類中提供了 集中callback回調 可以直接獲取轉換後的數據類型

比如String bitmap

當然也可以自定義,只需要繼承工具類中的Callback,然後通過Gson
及自己創建的數據類字節碼 進行轉化

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

再將該自定義Callback傳入請求的execute方法即可

總之這個工具類很方便,具體參開上面的鏈接

問題

不是說工具類有問題
而是在實際項目中,獲取的數據格式各不相同,每一種數據格式就需要新建一個數據bean,對應數據bean還需要創建對應Callback

這就會使得一個業務新建的類太多

遇到一堆業務時,定義的類的數量爆炸

然而數據bean的基本都會有success標誌 以及 msg 提示消息
以一個開源網絡api爲例 Gank的網站提供的api爲例 http://gank.io/api/data/Android/10/1

基本格式就是 下面這樣一個json
一般都是一個請求標記位 + 數據集合
{“error”:false,
“results”:[{… }]}

並且Callback回調中的 onError 和 onResponse處理很多感覺又可以複用

 .execute(new BitmapCallback()
{
    @Override
    public void onError(Request request, Exception e)
    {
        //根據錯誤類型決定展示錯誤界面
    }

    @Override
    public void onResponse(Bitmap bitmap)
    {
        //關閉正在加載界面,展示加載好數據的界面
    }
});

這裏做的就是對於對於不同數據bean的處理,以及回掉函數callback的封裝,便於應對各種問題
先創建了一個請求結果基類,只包含請求結果,對應gank的json數據

 public class BaseBean {
    /**
     * error : false
     */
    public String error;
}

然後直接通過GsonFormat插件複製整個gank 的json數據
自動生成獲取整個數據的bean ResultData
然後讓其繼承BaseBean 將其中集合部分 ResultsBean 換成泛型
下面就是修改後的數據bean
只要返回json類型爲 error + results類型的只需要新建一個results集合
中的子類數據bean將其傳入本來即可,用本類來接收整個數據

public class ResultData<T> extends BaseBean{
    private List<T> results;

    public List<T> getResults() {
        return results;
    }

    public void setResults(List<T> results) {
        this.results = results;
    }
}

如果數據集合有其他鍵值的 直接在本類中新加集合即可
比如還有另一個接口返回的時下面的數據
{“error”:”false”,”body”:[…]}
則增加一個新鍵值,獲取數據時注意鍵值不要選錯

public class ResultData<T> extends BaseBean{
    private List<T> results;
    private List<T> body;

    public List<T> getResults() {
        return results;
    }

    public void setResults(List<T> results) {
        this.results = results;
    }

    public List<T> getBody() {
        return body;
    }

    public void setBody(List<T> body) {
        this.body = body;
    }
}

當然也可以和後端商量,返回數據中集合部分統一用results或者body
就不需要額外添加鍵值了

有時候,還可能有下面這種數據
{“error”: false , “result”:[…],”count”: 100}
多了一個字段 count
那麼就在基類BaseBean中加上這個字段,其他完全不需要變動

public class BaseBean {
    /**
     * error : false
     */
    public String error;

    public int count;
}

數據bean基本處理完了

下面來實現對於callback封裝
先寫一個BaseCallback我們可以在這裏將部分網絡錯誤處理掉
比如登陸過期,無網絡訪問,返回404等
還可以在這裏關閉加載中界面(我在項目中加載中界面是一個全局的dialog)

public abstract class BaseCallback extends Callback{
    @Override
    public void onError(Call call, Exception e, int id) {
        // TODO: 
    }
}

查看了OkhttpUtils封裝源碼,發現網絡請求的code 如404等會被放在
異常類的最後,就是onError中的回掉參數e

下面重點來了,數據類型轉換,二次封裝callback
這裏主要進行數據類型轉換,這個類直接拿來用就可以了
沒什麼變動的地方

public abstract class ResponseCallback<T> extends BaseCallback {

    public Type mType;

    public ResponseCallback() {
        mType = getSuperclassTypeParameter(getClass());
    }

    static Type getSuperclassTypeParameter(Class<?> subclass) {
        Type superclass = subclass.getGenericSuperclass();
        if (superclass instanceof Class) {
            throw new RuntimeException("Missing type parameter.");
        }
        ParameterizedType parameterized = (ParameterizedType) superclass;
        return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
    }

    @Override
    public T parseNetworkResponse(Response response, int id) throws Exception {

        return new Gson().fromJson(response.body().string(), mType);
    }
}

傳入泛型,幫你轉換

最後我們來嘗試一把 看使用情況
直接訪問網絡,傳入ResponseCallback
傳入泛型ResultData < ResultBean >

    private void getData() {
        OkHttpUtils
                .get()
                .url("http://gank.io/api/data/Android/3/1")
                .build()
                .execute(new ResponseCallback<ResultData<ResultBean>>(){
                    @Override
                    public void onResponse(ResultData<ResultBean> response, int id) {
                        if (!response.error) {
                           mDataBinding.tv.setText( response.getResults().get(0).get_id());
                        }
                    }
                });
    }

獲取數據情況,我們的確拿到了數據

這裏寫圖片描述

再換個api試試 http://gank.io/api/history/content/day/2016/05/11

我們來看一些與第一個api獲取數據對比
這裏寫圖片描述
圖片看的不太清除
這裏解釋下,大家也可以去通過api訪問比對

{“error”:false,”result”:[…]} 一致 但 數組中內容格式完全不同
根據新數據結構創建新數據bean resultbean1

public class ResultBean1 {

    private String _id;
    private String content;
    private String publishedAt;
    private String title;

    public String get_id() {
        return _id;
    }

    public void set_id(String _id) {
        this._id = _id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getPublishedAt() {
        return publishedAt;
    }

    public void setPublishedAt(String publishedAt) {
        this.publishedAt = publishedAt;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

然後再次訪問,與上次只有url 和 ResultData中傳入的泛型不一致,其他直接複製過來的

    private void getData1() {

        OkHttpUtils
                .get()
                .url("http://gank.io/api/history/content/day/2016/05/11")
                .build()
                .execute(new ResponseCallback<ResultData<ResultBean1>>(){
                    @Override
                    public void onResponse(ResultData<ResultBean1> response, int id) {
                        if (!response.error) {
                            mDataBinding.tv.setText( response.getResults().get(0).get_id());
                        }
                    }
                });

    }

再來看一下結果
這裏寫圖片描述

同樣時拿到了id

框架搭好後,對於新的後臺接口,只需創建一個新的 返回的數據集合中的bean,傳入泛型即可
方便好用
看一下結構
這裏寫圖片描述

項目使用的依賴

    compile 'com.zhy:okhttputils:2.6.2'
    compile 'com.google.code.gson:gson:2.8.0'

源碼下載地址

參考文章

鴻洋okhttputils網絡訪問框架

okhttp簡單封裝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章