OkHttp基础学习(四),无网络读取本地缓存,有错误,待改正

学习资料:

  • [Android]Retrofit 2.0如何实现缓存
OkHttp基础学习(四),无网络读取本地缓存,有错误,待改正_第1张图片
没有网络,读取本地缓存

在手机状态栏中,并没有流量和WIFI联网的标志


1. 无网络,使用本地缓存

完整Activity代码:

public class NoNetworkActivity extends AppCompatActivity implements ResultCallback {
    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, "缓存文件夹创建成功");
        }
        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() {//添加网络拦截器
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        Response response = chain.proceed(request);
                        if (isNetworkConnected()) {
                            int maxAge = 60 * 60;// 有网 就1个小时可用
                            return response.newBuilder()
                                    .header("Cache-Control", "public, max-age=" + maxAge)
                                    .build();
                        } else {
                            int maxStale = 60 * 60 * 24 * 7;// 没网 就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);//失败回调
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //请求结果
                ResponseBody responseBody = null;
                try {
                    //判断请求是否取消
                    if (call.isCanceled()) {
                        sendFailResultCallback(new IOException("Request Canceled"));
                        return;
                    }
                    //获取请求结果 ResponseBody
                    responseBody = response.body();
                    //获取字符串
                    String json = responseBody.string();
                    Log.e("activity", json);
                    //成功回调
                    sendSuccessResultCallback(json);
                } catch (Exception e) {//发生异常,失败回调
                    sendFailResultCallback(e);
                } finally {//记得关闭操作
                    if (null != responseBody) {
                        responseBody.close();
                    }
                }
            }
        });

    }

    /**
     * 手机是否联网
     */
    private boolean isNetworkConnected() {
         //6.0 之后得使用 getApplicationContext()..getSystemService(...)
         //否则会内存泄漏
        ConnectivityManager manager = (ConnectivityManager)  getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = manager.getActiveNetworkInfo();
        return activeNetworkInfo.isConnected();
    }

    /**
     * 网络请求失败
     */
    @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线程回调
     */
     
    private void doSomething(Runnable runnable) {
        mPlatform.execute(runnable);
    }
}

cache(Cache,Size):添加缓存,指定缓存路径和空间大小

当设备断网时,通过Interceptor拦截器来进行网络访问,可以直接读取之前本地缓存

使用addNetworkInterceptor(Interceptor)OkHttpCLient添加一个网络拦截器

重写Interceptor内的intercept(Chain)方法,根据网络状态,设置缓存有效期

  • Cache-Control,缓存控制
  • public,所有网页信息都缓存
  • max-age,缓存有效期限,在这个期限内,不去再去进行网络访问
  • only-if-cached,只接受缓存的内容
  • max-stale,在设置期限内,客户端可以接受过去的内容

百度百科中Cache-control说得挺简单明了


2. Interceptor拦截器

Interceptor是一个接口

源码:

/*
 * 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();
  }
}

代码不多,但感觉接口的使用方式,可以学习


  • Interceptor WiKi
  • 拦截器 翻译

拦截器作用:

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

拦截器是一个强大的机制,可以监控,修改,重试 Call请求

个人理解:可以看作是海关,高速收费站,对进出的船或车,进行把控

OkHttp基础学习(四),无网络读取本地缓存,有错误,待改正_第2张图片
interceptors

贴个图,不为别的,就是感觉这个图:简洁,优雅,大方,逼格


拦截有两种:Application InterceptorNetwork Interceptor

一个灰色矩形块块就是一个Interceptor,一个OkHttpClient可以添加多个Interceptor拦截器

  • Application Interceptor主要多用于查看请求信息或者返回信息,如链接地址,头信息,参数等

  • Network Interceptor多用于对请求体Request或者响应体Response的改变,缓存处理用这个

暂时也就知道这么多了,Interceptor.Chain中3个方法具体做了啥,到了后面学习OkHttp工程流程,再学习了解


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. 最后

有错误,请指出

共勉 :)

你可能感兴趣的:(OkHttp基础学习(四),无网络读取本地缓存,有错误,待改正)