OkHttp基礎(chǔ)學(xué)習(xí)(四),無網(wǎng)絡(luò)讀取本地緩存,有錯(cuò)誤,待改正

學(xué)習(xí)資料:

沒有網(wǎng)絡(luò),讀取本地緩存

在手機(jī)狀態(tài)欄中,并沒有流量和WIFI聯(lián)網(wǎng)的標(biāo)志


1. 無網(wǎng)絡(luò),使用本地緩存

完整Activity代碼:

public class NoNetworkActivity extends AppCompatActivity implements ResultCallback<String> {
    private TextView tv_info;
    private String cachePath;
    private Platform mPlatform;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_no_network);
        //緩存路徑
        String path = Environment.getExternalStorageDirectory().getPath()
                + File.separator + Strings.FILE_PATH + File.separator + Strings.CACHE_PATH;
        File directory = new File(path);
        if (!directory.exists()) {
            if (directory.mkdirs()) ToastUtils.show(NoNetworkActivity.this, "緩存文件夾創(chuàng)建成功");
        }
        cachePath = directory.getPath();
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        mPlatform = Platform.get();
        tv_info = (TextView) findViewById(R.id.no_network_activity_tv);
        request();

    }

    private void request() {
        OkHttpClient okHttpClient = new OkHttpClient
                .Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .addNetworkInterceptor(new Interceptor() {//添加網(wǎng)絡(luò)攔截器
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        Response response = chain.proceed(request);
                        if (isNetworkConnected()) {
                            int maxAge = 60 * 60;// 有網(wǎng) 就1個(gè)小時(shí)可用
                            return response.newBuilder()
                                    .header("Cache-Control", "public, max-age=" + maxAge)
                                    .build();
                        } else {
                            int maxStale = 60 * 60 * 24 * 7;// 沒網(wǎng) 就1周可用
                            return response.newBuilder()
                                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                                    .build();
                        }
                    }
                })
                .cache(new Cache(new File(cachePath), 30 * 1024 * 1024))//最大 30m
                .build();

        Request request = new Request.Builder().url(Urls.GET_URL).build();

        Call call = okHttpClient.newCall(request);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                sendFailResultCallback(e);//失敗回調(diào)
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //請求結(jié)果
                ResponseBody responseBody = null;
                try {
                    //判斷請求是否取消
                    if (call.isCanceled()) {
                        sendFailResultCallback(new IOException("Request Canceled"));
                        return;
                    }
                    //獲取請求結(jié)果 ResponseBody
                    responseBody = response.body();
                    //獲取字符串
                    String json = responseBody.string();
                    Log.e("activity", json);
                    //成功回調(diào)
                    sendSuccessResultCallback(json);
                } catch (Exception e) {//發(fā)生異常,失敗回調(diào)
                    sendFailResultCallback(e);
                } finally {//記得關(guān)閉操作
                    if (null != responseBody) {
                        responseBody.close();
                    }
                }
            }
        });

    }

    /**
     * 手機(jī)是否聯(lián)網(wǎng)
     */
    private boolean isNetworkConnected() {
         //6.0 之后得使用 getApplicationContext()..getSystemService(...)
         //否則會內(nèi)存泄漏
        ConnectivityManager manager = (ConnectivityManager)  getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = manager.getActiveNetworkInfo();
        return activeNetworkInfo.isConnected();
    }

    /**
     * 網(wǎng)絡(luò)請求失敗
     */
    @Override
    public void sendFailResultCallback(final Exception e) {
        doSomething(new Runnable() {
            @Override
            public void run() {
                String info = "Fail Message --> " + e.getMessage();
                tv_info.setText(info);
            }
        });
    }

    /**
     * 請求成功
     */
    @Override
    public void sendSuccessResultCallback(final String result) {
        doSomething(new Runnable() {
            @Override
            public void run() {
                tv_info.setText(JsonFormatUtils.formatJson(result));
            }
        });
    }
    
    /**
     * UI線程回調(diào)
     */
     
    private void doSomething(Runnable runnable) {
        mPlatform.execute(runnable);
    }
}

cache(Cache,Size):添加緩存,指定緩存路徑和空間大小

當(dāng)設(shè)備斷網(wǎng)時(shí),通過Interceptor攔截器來進(jìn)行網(wǎng)絡(luò)訪問,可以直接讀取之前本地緩存

使用addNetworkInterceptor(Interceptor)OkHttpCLient添加一個(gè)網(wǎng)絡(luò)攔截器

重寫Interceptor內(nèi)的intercept(Chain)方法,根據(jù)網(wǎng)絡(luò)狀態(tài),設(shè)置緩存有效期

  • Cache-Control,緩存控制
  • public,所有網(wǎng)頁信息都緩存
  • max-age,緩存有效期限,在這個(gè)期限內(nèi),不去再去進(jìn)行網(wǎng)絡(luò)訪問
  • only-if-cached,只接受緩存的內(nèi)容
  • max-stale,在設(shè)置期限內(nèi),客戶端可以接受過去的內(nèi)容

百度百科中Cache-control說得挺簡單明了


2. Interceptor攔截器

Interceptor是一個(gè)接口

源碼:

/*
 * Copyright (C) 2014 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package okhttp3;

import java.io.IOException;

/**
 * Observes, modifies, and potentially short-circuits requests going out and the corresponding
 * responses coming back in. Typically interceptors add, remove, or transform headers on the request
 * or response.
 */
public interface Interceptor {
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    Request request();

    Response proceed(Request request) throws IOException;

    Connection connection();
  }
}

代碼不多,但感覺接口的使用方式,可以學(xué)習(xí)


攔截器作用:

Interceptors are a powerful mechanism that can monitor, rewrite, and retry
calls. Here's a simple interceptor that logs the outgoing request and the
incoming response

攔截器是一個(gè)強(qiáng)大的機(jī)制,可以監(jiān)控,修改,重試 Call請求

個(gè)人理解:可以看作是海關(guān),高速收費(fèi)站,對進(jìn)出的船或車,進(jìn)行把控

interceptors

貼個(gè)圖,不為別的,就是感覺這個(gè)圖:簡潔,優(yōu)雅,大方,逼格


攔截有兩種:Application InterceptorNetwork Interceptor

一個(gè)灰色矩形塊塊就是一個(gè)Interceptor,一個(gè)OkHttpClient可以添加多個(gè)Interceptor攔截器

  • Application Interceptor主要多用于查看請求信息或者返回信息,如鏈接地址,頭信息,參數(shù)等

  • Network Interceptor多用于對請求體Request或者響應(yīng)體Response的改變,緩存處理用這個(gè)

暫時(shí)也就知道這么多了,Interceptor.Chain中3個(gè)方法具體做了啥,到了后面學(xué)習(xí)OkHttp工程流程,再學(xué)習(xí)了解


2.1 Application Interceptor 簡單使用

代碼:直接加在OkHttpClient中的addNetworkInterceptor前就可以

     .addInterceptor(new Interceptor() {
             @Override
             public Response intercept(Chain chain) throws IOException {
             Request request = chain.request();

             long t1 = System.nanoTime();
             String info_1 = String.format("Sending request %s on %s%n%s", request.url(),
                 chain.connection(), request.headers());
                Log.e("info1", "-->" + info_1);

                Response response = chain.proceed(request);
                long t2 = System.nanoTime();
                String info_2 = String.format("Received response for %s in %.1fms%n%s".toLowerCase(),
             response.request().url(), (t2 - t1) / 1e6d, response.headers());
             Log.e("info2", "-->" + info_2);
             return response;
         }
     })

輸出Log信息:

Application Interceptor 攔截信息

3. 最后

有錯(cuò)誤,請指出

共勉 :)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容