天天看點

Android鍊式調用 - 打造第三方的網絡引擎

1. 概述

  上一期我們提了一下Volley,Okhttp,Retrofit到底應該選哪一個?但是的确目前第三方的網絡架構比較多入流的不入流的打醬油的自己寫的等等等等,也不知道再等個幾十年會出什麼樣的,到時候我們可能還是要換,然而随着版本的疊代這是一個很頭疼的事情,如果要更換更好的網絡架構成本就比較高了,今天我們來看一下怎麼樣打造一套網絡架構引擎,一方面為了封裝,一方面為了友善切換網絡架構。

所有分享大綱:2017Android進階之路與你同行

視訊講解位址:周日晚上八點

Android鍊式調用 - 打造第三方的網絡引擎

    

2. 套路分析

  一般在開發中我們往往還要根據需求對第三方的網絡架構進行封裝,如Okhttp、Volley、Retrofit等等。封裝是為了更符合我們的項目需求,友善調用,這一步可能少不了,那麼我們隻需要思考怎麼樣才能做到任意切換網絡架構呢?如果能夠随意切換最好。

  其實我們請求的資料的時候基本是類似的無非就是擷取資料和顯示資料,可問題就在于各大網絡架構的套路不一樣,是以隻要解決這個問題就好了。那麼這個時候我們隻需要自己搞一個套路就好,我們Activity ->自己的套路 ->第三大網絡架構遵循我們的的套路->第三大網絡架構,但是這樣是不是會有問題呢?可能會有些許問題,畢竟不是直接的血緣關系,但是隻要代碼好擴充,随着項目的推進是很好完善的。

Android鍊式調用 - 打造第三方的網絡引擎

3. 實作

自定義一套規則,目前可以簡單點,當然也可以根據項目需求稍微複雜點 IHttpEngine:

/**
 * Created by Darren on 2017/03/01
 * Email: [email protected]
 * Description: 網絡引擎的規範
 */
public interface HttpEngine {
    // post 送出
    public void post(Context context, String url, Map<String, Object> params, HttpCallBack httpCallBack, boolean cache);

    // get 送出
    public void get(Context context, String url, Map<String, Object> params, HttpCallBack httpCallBack, boolean cache);

    // 取消請求
    // 下載下傳檔案
    // 上傳檔案
    // https添加安全證書
}
           

定義自己的套路HttpUtils:

/**
 * Created by Darren on 2017/03/01
 * Email: [email protected]
 * Description:
 */
public class HttpUtils {
    // 上下文
    private Context mContext;
    // 網絡通路引擎
    private static HttpEngine mHttpEngine = new OkHttpEngine();
    // 接口位址
    private String mUrl;
    // 請求參數
    private Map<String, Object> mParams;
    // get請求辨別
    private final int GET_REQUEST = ;
    // post請求辨別
    private final int POST_REQUEST = ;
    // 請求的方式
    private int mRequestMethod = GET_REQUEST;

    // 是否緩存
    private boolean mCache = false;

    // 切換引擎
    public void exchangeEngine(HttpEngine httpEngine){
        this.mHttpEngine = httpEngine;
    }

    // 可以在Application中配置HttpEngine 
    public static initEngine(HttpEngine httpEngine){
         this.mHttpEngine = httpEngine;
   }

    private HttpUtils(Context context) {
        this.mContext = context;
        mParams = new HashMap<>();
    }

    public static HttpUtils with(Context context) {
        return new HttpUtils(context);
    }

    public HttpUtils url(String url) {
        mUrl = url;
        return this;
    }

    // 執行方法
    public void execute(HttpCallBack httpCallBack) {
        if (TextUtils.isEmpty(mUrl)) {
            throw new NullPointerException("通路路徑不能為空");
        }

        if (mRequestMethod == GET_REQUEST) {
            get(mUrl, mParams, httpCallBack);
        }

        if (mRequestMethod == POST_REQUEST) {
            post(mUrl, mParams, httpCallBack);
        }
    }
}
           

封裝一個簡單的事例OkhttpEnigne:

/**
 * Created by Darren on 2017/03/01
 * Email: [email protected]
 * Description: OKHttp引擎
 */
public class OkHttpEngine implements HttpEngine {

    private static OkHttpClient mOkHttpClient = new OkHttpClient();

    @Override
    public void post(final Context context, String url, Map<String, Object> params, final HttpCallBack httpCallBack, final boolean cache) {
        // 省略部分代碼......
        RequestBody requestBody = appendBody(params);
        Request request = new Request.Builder()
                .url(url)
                .tag(context)
                .post(requestBody)
                .build();

        mOkHttpClient.newCall(request).enqueue(
                new Callback() {
                    @Override
                    public void onFailure(Call call, final IOException e) {
                        executeError(httpCallBack, e);
                    }

                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        String resultJson = response.body().string();
                        executeSuccessMethod(httpCallBack, resultJson);
                        // 緩存處理,下一期我們沒事幹,自己手寫資料庫架構
                    }
                }
        );
    }

    /**
    *  執行成功的方法
    **/
    private void executeSuccessMethod(final HttpCallBack httpCallBack, final String resultJson) {
            try {
                HttpUtils.handler.post(new Runnable() {
                    @Override
                    public void run() {
                        httpCallBack.onSucceed(resultJson);
                    }
                });
            } catch (Exception e) {
                executeError(httpCallBack, e);
                e.printStackTrace();
            }
    }

    /**
    *  執行失敗的方法
    */
    private void executeError(final HttpCallBack httpCallBack, final Exception e) {
            HttpUtils.handler.post(new Runnable() {
                @Override
                public void run() {
                    httpCallBack.onError(e);
                }
            });
    }

    @Override
    public void get(Context context, String url, Map<String, Object> params, final HttpCallBack httpCallBack, boolean cache) {
        // 省略部分代碼......
        Request.Builder requestBuilder = new Request.Builder().url(url).tag(context);
        Request request = requestBuilder.build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                    httpCallBack.onError(e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String resultJson = response.body().string();
                // 當然有的時候還需要不同的些許處理
                HttpUtils.handler.post(new Runnable() {
                    @Override
                    public void run() {
                       httpCallBack.onSucceed(result);
                    }
               });
            }
        });
    }
           

  我們可以自己試試Retrofit的方式,這裡我就不寫了,畢竟很多人對于Retrofit并不是特别了解。自己也希望可以從RxJava開始寫文章然後一步一步的上升到Retrofit。總之現在已經有了一個預設的OkHttpEngine了,如果需要配置或者切換我們需要去自定義一個引擎,然後切換到目前引擎就可以了,我們看一下怎麼使用:

HttpUtils.with(context)
     .exchangeEngine(new RetrofitEngine());// 切換成Retrofit引擎
     .url(UrlConstant.CITY_MAIN_PAGE) // 路徑
     .addParam("city", mCurrentCity)  // 添加參數
     .cache(true)  // 需要讀緩存
     .post()  // post送出
     .execute(new HttpCallBack<CityFragmentEntity>() {
             @Override
            public void onError(Exception e) {
                    // 錯誤回調
            }

            @Override
            public void onSucceed(CityFragmentEntity result) {
                   // result  傳回的解析好的對象  可以直接操作不需要再Json解析
                   // 成功的回調
            }
     });
           

  這其實也沒什麼就是友善以後如果有了更好的第三方網絡架構那麼我們可以在Application中配置引擎,也可以每次請求的時候指定不同的引擎,這其實就是面向接口程式設計而已,這裡還遺留了一個問題就是資料緩存,下一期我們需要利用面向對象的思想自己動手去寫一套資料庫封裝,我們得按需定制把資料庫寫到外部存儲卡中,還需要考慮資料庫加密,Query懶加載,Lucene輔助搜尋等等等等,不光是為了造輪子而是為了更好的了解其他資料庫架構的原理。

所有分享大綱:2017Android進階之路與你同行

視訊講解位址:周日晚上八點

繼續閱讀