成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Android網(wǎng)絡(luò)編程5之OkHttp2.x用法全解析

wemall / 3344人閱讀

摘要:需要注意的是回調(diào)并不是在線程。也可以通過來同時(shí)取消多個(gè)請求。在開始創(chuàng)建的時(shí)候配置好,在請求網(wǎng)絡(luò)的時(shí)候用將請求的結(jié)果回調(diào)給線程。最后調(diào)用這個(gè)的方法請求成功使用起來簡單多了,而且請求結(jié)果回調(diào)是在線程的。

前言

講完了Volley,我們接下來看看目前比較火的網(wǎng)絡(luò)框架OkHttp, 它處理了很多網(wǎng)絡(luò)疑難雜癥:會從很多常用的連接問題中自動恢復(fù)。如果您的服務(wù)器配置了多個(gè)IP地址,當(dāng)?shù)谝粋€(gè)IP連接失敗的時(shí)候,OkHttp會自動嘗試下一個(gè)IP,此外OkHttp還處理了代理服務(wù)器問題和SSL握手失敗問題。

1.使用前準(zhǔn)備

eclipse引入jar包地址:
okhttp-2.7.5.jar
okio-1.7.0.jar

Android Studio 配置gradle:

  compile "com.squareup.okhttp:okhttp:2.7.5"
  compile "com.squareup.okio:okio:1.7.0"
2.異步GET請求

最簡單的get請求,老規(guī)矩請求百度:

      private void getAsynHttp() {
        //創(chuàng)建okHttpClient對象
        OkHttpClient mOkHttpClient = new OkHttpClient();
        final Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .build();
        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 str = response.body().string();
                Log.i("wangshu", str);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplication(), "請求成功", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

運(yùn)行程序log打印出來的是百度首頁的html文件,基本的步驟很簡單,就是創(chuàng)建OkHttpClient、Request和Call,最后調(diào)用Call的enqueue()方法。但是每次這么寫肯定是很麻煩,肯定是要進(jìn)行封裝的。需要注意的是onResponse回調(diào)并不是在UI線程。

3.同步GET請求
 private String getSyncHttp() throws IOException{
        OkHttpClient mOkHttpClient = new OkHttpClient();
        //創(chuàng)建請求Request
        final Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .build();
        Call call = mOkHttpClient.newCall(request);
        Response mResponse=call.execute();
        if (mResponse.isSuccessful()) {
            return mResponse.body().string();
        } else {
            throw new IOException("Unexpected code " + mResponse);
        }
    }

同步Get請求和異步調(diào)用區(qū)別就是調(diào)用了call的execute()方法。

4.異步POST請求
    private void postAsynHttp() {
        OkHttpClient mOkHttpClient = new OkHttpClient();
        RequestBody formBody = new FormEncodingBuilder()
                .add("size", "10")
                .build();

        Request request = new Request.Builder()
                .url("http://api.1-blog.com/biz/bizserver/article/list.do")
                .post(formBody)
                .build();
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {

            }

            @Override
            public void onResponse(Response response) throws IOException {
                String str = response.body().string();
                Log.i("wangshu", str);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

post與get不同的就是要要創(chuàng)建RequestBody并傳進(jìn)Request中,同樣onResponse回調(diào)不是在UI線程。

5.請求緩存設(shè)置

首先我們設(shè)置緩存路徑和大小并設(shè)置給OkHttpClient:

 mOkHttpClient = new OkHttpClient();
 File sdcache = getExternalCacheDir();
 int cacheSize = 10 * 1024 * 1024;
 mOkHttpClient.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));

接下來異步GET請求baidu:

 private void getAsynHttp() {
        //創(chuàng)建請求Request
        final Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .build();
        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 {
                if (null != response.cacheResponse()) {
                    String str = response.cacheResponse().toString();
                    Log.i("wangshu", "cache---" + str);
                } else {
                    response.body().string();
                    String str=response.networkResponse().toString();
                    Log.i("wangshu", "network---" + str);
                }
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        });
    }

第一次請求會請求網(wǎng)絡(luò)得到數(shù)據(jù),第二次以及后面的請求則會從緩存中取出數(shù)據(jù):

當(dāng)然也有種情況是有的請求每次都需要最新的數(shù)據(jù),則在創(chuàng)建Request,來設(shè)置cacheControl為“CacheControl.FORCE_NETWORK”,用來表示請求會一直請求網(wǎng)絡(luò)得到數(shù)據(jù):

  final Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .cacheControl(CacheControl.FORCE_NETWORK)
                .build();

運(yùn)行程序結(jié)果為:

6.設(shè)置超時(shí)時(shí)間

另外我們也需要設(shè)置超時(shí)的時(shí)間用來處理各種網(wǎng)絡(luò)超時(shí)的情況,超時(shí)的原因可能是網(wǎng)絡(luò)問題也可能是服務(wù)器響應(yīng)慢等問題,OkHttp當(dāng)然不會忽略這一點(diǎn),它支持連接、讀取和寫入超時(shí)的時(shí)間設(shè)置:

        mOkHttpClient = new OkHttpClient();
        mOkHttpClient.setConnectTimeout(15, TimeUnit.SECONDS);
        mOkHttpClient.setWriteTimeout(20, TimeUnit.SECONDS);
        mOkHttpClient.setReadTimeout(20, TimeUnit.SECONDS);
7.取消請求

使用call.cancel()可以立即停止掉一個(gè)正在執(zhí)行的call。如果一個(gè)線程正在寫請求或者讀響應(yīng),將會引發(fā)IOException。當(dāng)用戶離開一個(gè)應(yīng)用時(shí)或者跳到其他界面時(shí),使用Call.cancel()可以節(jié)約網(wǎng)絡(luò)資源,另外不管同步還是異步的call都可以取消。
也可以通過tags來同時(shí)取消多個(gè)請求。當(dāng)你構(gòu)建一請求時(shí),使用RequestBuilder.tag(tag)來分配一個(gè)標(biāo)簽。之后你就可以用OkHttpClient.cancel(tag)來取消所有帶有這個(gè)tag的call。

為了模擬這個(gè)場景我們首先創(chuàng)建一個(gè)定時(shí)的線程池:

   private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);

接下來的代碼為:

 private  void cancel(){
        final Request request = new Request.Builder()
                .url("http://www.baidu.com")
                .cacheControl(CacheControl.FORCE_NETWORK)
                .build();
        Call call=null;
        call = mOkHttpClient.newCall(request);
        final Call finalCall = call;
        //100毫秒后取消call
        executor.schedule(new Runnable() {
            @Override public void run() {
                finalCall.cancel();
            }
        }, 100, TimeUnit.MILLISECONDS);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
            }

            @Override
            public void onResponse(final Response response) {
                if (null != response.cacheResponse()) {
                    String str = response.cacheResponse().toString();
                    Log.i("wangshu", "cache---" + str);
                } else {
                    try {
                        response.body().string();

                    } catch (IOException e) {
                        Log.i("wangshu", "IOException");
                        e.printStackTrace();
                    }
                    String str = response.networkResponse().toString();
                    Log.i("wangshu", "network---" + str);
                }
            }
        });
           Log.i("wangshu", "是否取消成功"+call.isCanceled());
    }

100毫秒后調(diào)用call.cancel(),為了能讓請求耗時(shí),我們設(shè)置每次請求都要請求網(wǎng)絡(luò),運(yùn)行程序并且不斷的快速點(diǎn)擊發(fā)送請求按鈕:

很明顯每次cancel()都失敗了,仍舊成功的訪問了網(wǎng)絡(luò),在cancel()時(shí)已經(jīng)有讀寫操作了所以會報(bào)IOException。每隔100毫秒來調(diào)用call.cancel()顯然時(shí)間間隔太長,我們設(shè)置為1毫秒并不斷的快速的點(diǎn)擊發(fā)送請求按鈕:

沒有請求網(wǎng)絡(luò)的log,幾乎每次都取消成功了。

8.關(guān)于封裝

如果每次請求網(wǎng)絡(luò)都需要寫重復(fù)的代碼絕對是令人頭疼的,網(wǎng)上也有很多對OkHttp封裝的優(yōu)秀開源項(xiàng)目,功能也非常強(qiáng)大,封裝的意義就在于更加方便的使用,具有拓展性,但是對OkHttp封裝最需要解決的是以下的兩點(diǎn):

避免重復(fù)代碼調(diào)用

將請求結(jié)果回調(diào)改為UI線程

根據(jù)以上兩點(diǎn),我們也簡單封裝一下,在此只是舉個(gè)例子,如果想要使用OkHttp封裝的開源庫,推薦使用OkHttpFinal。
首先呢我們寫一個(gè)抽象類用于請求回調(diào):

public abstract class ResultCallback
{
    public abstract void onError(Request request, Exception e);

    public abstract void onResponse(Response response);
}

接下來封裝OkHttp,并實(shí)現(xiàn)了異步GET請求:

public class OkHttpEngine {
    private static OkHttpEngine mInstance;
    private OkHttpClient mOkHttpClient;
    private Handler mHandler;

    public static OkHttpEngine getInstance() {
        if (mInstance == null) {
            synchronized (OkHttpEngine.class) {
                if (mInstance == null) {
                    mInstance = new OkHttpEngine();
                }
            }
        }
        return mInstance;
    }

    private OkHttpEngine() {
        mOkHttpClient = new OkHttpClient();
        mOkHttpClient.setConnectTimeout(15, TimeUnit.SECONDS);
        mOkHttpClient.setWriteTimeout(20, TimeUnit.SECONDS);
        mOkHttpClient.setReadTimeout(20, TimeUnit.SECONDS);
        mHandler = new Handler();

    }

    public OkHttpEngine setCache(Context mContext) {
        File sdcache = mContext.getExternalCacheDir();
        int cacheSize = 10 * 1024 * 1024;
        mOkHttpClient.setCache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
        return mInstance;
    }

    /**
     * 異步get請求
     * @param url
     * @param callback
     */
    public void getAsynHttp(String url, ResultCallback callback) {

        final Request request = new Request.Builder()
                .url(url)
                .build();
        Call call = mOkHttpClient.newCall(request);
        dealResult(call, callback);

    }

    private void dealResult(Call call, final ResultCallback callback) {
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                sendFailedCallback(request, e, callback);
            }

            @Override
            public void onResponse(final Response response) throws IOException {
                sendSuccessCallback(response, callback);
            }

            private void sendSuccessCallback(final Response object, final ResultCallback callback) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (callback != null) {
                            callback.onResponse(object);
                        }
                    }
                });
            }

            private void sendFailedCallback(final Request request, final Exception e, final ResultCallback callback) {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (callback != null)
                            callback.onError(request, e);
                    }
                });
            }

        });
    }
}

原理很簡單就是,寫一個(gè)雙重檢查模式的單例,不了解雙重檢查模式的請查看設(shè)計(jì)模式之單例模式的七種寫法這篇文章。在開始創(chuàng)建的時(shí)候配置好OkHttpClient,在請求網(wǎng)絡(luò)的時(shí)候用Handler將請求的結(jié)果回調(diào)給UI線程。

最后調(diào)用這個(gè)OkHttpEngine的getAsynHttp()方法:

  OkHttpEngine.getInstance().getAsynHttp("http://www.baidu.com", new ResultCallback() {
            @Override
            public void onError(Request request, Exception e) {

            }

            @Override
            public void onResponse(Response response) {
                String str = response.networkResponse().toString();
                Log.i("wangshu", str);
                Toast.makeText(getApplicationContext(), "請求成功", Toast.LENGTH_SHORT).show();
            }
        });

使用起來簡單多了,而且請求結(jié)果回調(diào)是在UI線程的。下一篇我們會講到OkHttp3,來看看它與OkHttp2.x之間的使用方式上有什么區(qū)別。

github源碼下載

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70589.html

相關(guān)文章

  • Android網(wǎng)絡(luò)編程6OkHttp3用法解析

    摘要:使用前準(zhǔn)備配置添加網(wǎng)絡(luò)權(quán)限異步請求慣例,請求百度可以省略,默認(rèn)是請求請求成功與版本并沒有什么不同,比較郁悶的是回調(diào)仍然不在線程。 前言 上一篇介紹了OkHttp2.x的用法,這一篇文章我們來對照OkHttp2.x版本來看看,OkHttp3使用起來有那些變化。當(dāng)然,看這篇文章前建議看一下前一篇文章Android網(wǎng)絡(luò)編程(五)OkHttp2.x用法全解析。 1.使用前準(zhǔn)備 Android ...

    Amos 評論0 收藏0
  • Android網(wǎng)絡(luò)編程7源碼解析OkHttp前篇[請求網(wǎng)絡(luò)]

    摘要:異步請求當(dāng)正在運(yùn)行的異步請求隊(duì)列中的數(shù)量小于并且正在運(yùn)行的請求主機(jī)數(shù)小于時(shí)則把請求加載到中并在線程池中執(zhí)行,否則就再入到中進(jìn)行緩存等待。通常情況下攔截器用來添加,移除或者轉(zhuǎn)換請求或者響應(yīng)的頭部信息。 前言 學(xué)會了OkHttp3的用法后,我們當(dāng)然有必要來了解下OkHttp3的源碼,當(dāng)然現(xiàn)在網(wǎng)上的文章很多,我仍舊希望我這一系列文章篇是最簡潔易懂的。 1.從請求處理開始分析 首先OKHttp...

    blastz 評論0 收藏0
  • Android網(wǎng)絡(luò)編程3Volley用法解析

    摘要:前言想必很多人都用過,為了建立網(wǎng)絡(luò)編程的知識體系,是必須要講的知識點(diǎn),所以我這里有必要再次介紹一下的使用。簡介在年大會上推出了一個(gè)新的網(wǎng)絡(luò)通信框架。在使用前請下載庫并放在目錄下并到工程中。 前言 Volley想必很多人都用過,為了建立網(wǎng)絡(luò)編程的知識體系,Volley是必須要講的知識點(diǎn),所以我這里有必要再次介紹一下Volley的使用。 1.Volley簡介 在2013年Google I/...

    Code4App 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<