Android鏈?zhǔn)秸{(diào)用 - 打造第三方的網(wǎng)絡(luò)引擎

1. 概述


上一期我們提了一下Volley,Okhttp,Retrofit到底應(yīng)該選哪一個?但是的確目前第三方的網(wǎng)絡(luò)框架比較多,也不知道再等個幾十年會出什么樣的,到時候我們可能還是要換,然而隨著版本的迭代這是一個很頭疼的事情,如果要更換更好的網(wǎng)絡(luò)框架成本就比較高了,今天我們來看一下怎么樣打造一套網(wǎng)絡(luò)框架引擎,一方面為了封裝,一方面為了方便切換網(wǎng)絡(luò)框架。

所有分享大綱:2017Android進(jìn)階之路與你同行

視頻講解地址:http://pan.baidu.com/s/1pKWuZrX

2. 套路分析


一般在開發(fā)中我們往往還要根據(jù)需求對第三方的網(wǎng)絡(luò)框架進(jìn)行封裝,如Okhttp、Volley、Retrofit等等。封裝是為了更符合我們的項目需求,方便調(diào)用,這一步可能少不了,那么我們只需要思考怎么樣才能做到任意切換網(wǎng)絡(luò)框架呢?如果能夠隨意切換最好。

其實我們請求的數(shù)據(jù)的時候基本是類似的無非就是獲取數(shù)據(jù)和顯示數(shù)據(jù),可問題就在于各大網(wǎng)絡(luò)框架的套路不一樣,所以只要解決這個問題就好了。那么這個時候我們只需要自己搞一個套路就好,我們Activity ->自己的套路 ->第三大網(wǎng)絡(luò)框架遵循我們的的套路->第三大網(wǎng)絡(luò)框架,但是這樣是不是會有問題呢?可能會有些許問題,畢竟不是直接的血緣關(guān)系,但是只要代碼好擴(kuò)展,隨著項目的推進(jìn)是很好完善的。

自定義引擎類圖.png

3. 實現(xiàn)


自定義一套規(guī)則,目前可以簡單點,當(dāng)然也可以根據(jù)項目需求稍微復(fù)雜點 IHttpEngine:

/**
 * Created by Darren on 2017/03/01
 * Email: 240336124@qq.com
 * Description: 網(wǎng)絡(luò)引擎的規(guī)范
 */
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: 240336124@qq.com
 * Description:
 */
public class HttpUtils {
    // 上下文
    private Context mContext;
    // 網(wǎng)絡(luò)訪問引擎
    private static HttpEngine mHttpEngine = new OkHttpEngine();
    // 接口地址
    private String mUrl;
    // 請求參數(shù)
    private Map<String, Object> mParams;
    // get請求標(biāo)識
    private final int GET_REQUEST = 0x0011;
    // post請求標(biāo)識
    private final int POST_REQUEST = 0x0022;
    // 請求的方式
    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;
    }

    // 執(zhí)行方法
    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: 240336124@qq.com
 * 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);
                        // 緩存處理,下一期我們沒事干,自己手寫數(shù)據(jù)庫框架
                    }
                }
        );
    }
    
    /**
    *  執(zhí)行成功的方法
    **/
    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();
            }
    }
    
    /**
    *  執(zhí)行失敗的方法
    */
    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();
                // 當(dāng)然有的時候還需要不同的些許處理
                HttpUtils.handler.post(new Runnable() {
                    @Override
                    public void run() {
                       httpCallBack.onSucceed(result);
                    }
               });
            }
        });
    }

我們可以自己試試Retrofit的方式,這里我就不寫了,畢竟很多人對于Retrofit并不是特別了解。自己也希望可以從RxJava開始寫文章然后一步一步的上升到Retrofit。總之現(xiàn)在已經(jīng)有了一個默認(rèn)的OkHttpEngine了,如果需要配置或者切換我們需要去自定義一個引擎,然后切換到當(dāng)前引擎就可以了,我們看一下怎么使用:

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

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

這其實也沒什么就是方便以后如果有了更好的第三方網(wǎng)絡(luò)框架那么我們可以在Application中配置引擎,也可以每次請求的時候指定不同的引擎,這其實就是面向接口編程而已,這里還遺留了一個問題就是數(shù)據(jù)緩存,下一期我們需要利用面向?qū)ο蟮乃枷胱约簞邮秩懸惶讛?shù)據(jù)庫封裝,我們得按需定制把數(shù)據(jù)庫寫到外部存儲卡中,還需要考慮數(shù)據(jù)庫加密,Query懶加載,Lucene輔助搜索等等等等,不光是為了造輪子而是為了更好的了解其他數(shù)據(jù)庫框架的原理。

所有分享大綱:2017Android進(jìn)階之路與你同行

視頻講解地址:http://pan.baidu.com/s/1pKWuZrX

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,476評論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,251評論 4 61
  • 寫作果然是鍛煉思維的過程,讀的時候感覺自己都懂得,在寫的時候就露餡了,寫得很亂,還需要找時間鉆研,最近就和這個問題...
    海西情歌閱讀 271評論 0 0
  • 你給我的歡樂和痛苦 就像一棵烏雲(yún)中聳立的白樺 我不抱怨。一切都那麼可愛 雲(yún)越黑,白樺就變得更亮 早課抄了拉脫維亞女...
    東豐林波閱讀 339評論 0 0