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

学习资料:

没有网络,读取本地缓存

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


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

完整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, "缓存文件夹创建成功");
        }
        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();
  }
}

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


拦截器作用:

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请求

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

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

有错误,请指出

共勉 :)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容