Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >改造+ OkHTTP -响应缓存不工作

改造+ OkHTTP -响应缓存不工作
EN

Stack Overflow用户
提问于 2015-04-27 00:52:03
回答 4查看 5.6K关注 0票数 5

我知道有很多类似的问题,但我都读过了,没有一个真的有帮助。

所以,我的问题是:

我正在使用retrofit + okhttp从API中获取一些数据,我想缓存它们。不幸的是,我没有API服务器的管理权限,所以我不能修改服务器返回的头。(目前,服务器返回缓存-控制:私有)

因此,我决定使用okhttp头欺骗插入适当的缓存头。可悲的是,不管我做什么,缓存似乎都不起作用。

我初始化api服务如下:

代码语言:javascript
运行
AI代码解释
复制
int cacheSize = 10 * 1024 * 1024; // 10 MiB
File cacheFile = new File(context.getCacheDir(), "thumbs");
final Cache cache = new Cache(cacheFile, cacheSize);

OkHttpClient client = new OkHttpClient();
client.setCache(cache);
client.interceptors().add(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response originalResponse = chain.proceed(chain.request());
        return originalResponse.newBuilder()
                .removeHeader("Access-Control-Allow-Origin")
                .removeHeader("Vary")
                .removeHeader("Age")
                .removeHeader("Via")
                .removeHeader("C3-Request")
                .removeHeader("C3-Domain")
                .removeHeader("C3-Date")
                .removeHeader("C3-Hostname")
                .removeHeader("C3-Cache-Control")
                .removeHeader("X-Varnish-back")
                .removeHeader("X-Varnish")
                .removeHeader("X-Cache")
                .removeHeader("X-Cache-Hit")
                .removeHeader("X-Varnish-front")
                .removeHeader("Connection")
                .removeHeader("Accept-Ranges")
                .removeHeader("Transfer-Encoding")
                .header("Cache-Control", "public, max-age=60")
              //.header("Expires", "Mon, 27 Apr 2015 08:15:14 GMT")
                .build();
    }
});

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint(API_ROOT)
    .setLogLevel(RestAdapter.LogLevel.HEADERS_AND_ARGS)
    .setClient(new OkClient(client))
    .setConverter(new SimpleXMLConverter(false))
    .setRequestInterceptor(new RequestInterceptor() {
        @Override
        public void intercept(RequestFacade request) {
            if (Network.isConnected(context)) {
                int maxAge = 60; // read from cache for 2 minutes
                request.addHeader("Cache-Control", "public, max-age=" + maxAge);
            } else {
                int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
                request.addHeader("Cache-Control",
                    "public, only-if-cached, max-stale=" + maxStale);
            }
        }
    })
    .build();
api = restAdapter.create(ApiService.class);

当然,没有必要删除所有这些标题,但我希望尽可能干净地处理响应,以排除来自这些额外标题的一些干扰。

正如你所看到的,我也试图欺骗过期和日期头(我试着删除它们,设置它们,这样它们之间就会有最大的年龄差异,并且在很长的将来也会出现过期)。我也尝试了各种缓存控制值,但没有运气。

我确保了cacheFile的存在、isDirectory的存在以及应用程序的可写性。

这些是通过改进直接记录的请求和响应头:

代码语言:javascript
运行
AI代码解释
复制
Request:
Cache-Control: public, max-age=60
---> END HTTP (no body)

Response:
Date: Mon, 27 Apr 2015 08:41:10 GMT
Server: Apache/2.2.22 (Ubuntu)
Expires: Mon, 27 Apr 2015 08:46:10 GMT
Content-Type: text/xml; charset=UTF-8
OkHttp-Selected-Protocol: http/1.1
OkHttp-Sent-Millis: 1430124070000
OkHttp-Received-Millis: 1430124070040
Cache-Control: public, max-age=60
<--- END HTTP (-1-byte body)
<--- BODY: ...

最后,一个奇怪的事件:在某个时候,缓存工作了几分钟。我得到了合理的点击计数,甚至离线请求返回缓存的值。(这是在使用此处发布的确切设置时发生的),但当我重新启动应用程序时,一切都恢复到“正常”(常量点击计数0)。

如果有人知道这里有什么问题,我很乐意提供帮助:)

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-06-05 16:18:31

使用networkInterceptors()而不是拦截器()。这与删除任何与缓存有关的头的策略结合起来都是可行的。这是简单的答案。

当您使用拦截器更改标头时,它在调用CacheStrategy.isCacheable()之前不会进行任何调整。值得研究一下CacheStrategy和CacheControl类,看看OKHttp如何处理与缓存相关的头文件。在ctrl+f上做http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html“缓存”也是值得的

我不确定networkInterceptors()和拦截器()文档是不清楚还是有bug。一旦我进一步研究这个问题,我会更新这个答案。

票数 9
EN

Stack Overflow用户

发布于 2017-03-01 21:30:22

这里还有一件事要补充,除了的回答外,仅仅为了确认OkHttp3缓存将不能处理post请求。

票数 8
EN

Stack Overflow用户

发布于 2020-05-06 17:44:29

一整天之后,我发现我的离线缓存并不是因为我在API类型中使用POST而起作用的。当我把它改成GET的时候,它就起作用了!

代码语言:javascript
运行
AI代码解释
复制
@GET("/ws/audioInactive.php")
Call<List<GetAudioEntity>> getAudios();

我的整堂课。

代码语言:javascript
运行
AI代码解释
复制
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.limnet.iatia.App;
import com.limnet.iatia.netio.entity.registration.APIInterfaceProviderIMPL;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RHTRetroClient {

    public static final String BASE_URL = "https://abc.pro";
    private static Retrofit retrofit = null;
    private static RHTRetroClient mInstance;

    private static final long cacheSize = 10 * 1024 * 1024; // 10 MB
    public static final String HEADER_CACHE_CONTROL = "Cache-Control";
    public static final String HEADER_PRAGMA = "Pragma";


    private RHTRetroClient() {
        Gson gson = new GsonBuilder()
                .setLenient()
                .create();
        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();

        Cache cache = new Cache(new File(App.getAppContext().getCacheDir(), "soundbites"),cacheSize);

        OkHttpClient client = new OkHttpClient.Builder()
                .cache(cache)
                .addInterceptor(httpLoggingInterceptor()) // used if network off OR on
                .addNetworkInterceptor(networkInterceptor()) // only used when network is on
                .addInterceptor(offlineInterceptor())
                .build();

        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }

    /**
     * This interceptor will be called both if the network is available and if the network is not available
     *
     * @return
     */
    private static Interceptor offlineInterceptor() {
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Log.d("rht", "offline interceptor: called.");
                Request request = chain.request();

                // prevent caching when network is on. For that we use the "networkInterceptor"
                if (!App.hasNetwork()) {
                    CacheControl cacheControl = new CacheControl.Builder()
                            .maxStale(7, TimeUnit.DAYS)
                            .build();

                    request = request.newBuilder()
                            .removeHeader(HEADER_PRAGMA)
                            .removeHeader(HEADER_CACHE_CONTROL)
                            .cacheControl(cacheControl)
                            .build();
                }

                return chain.proceed(request);
            }
        };
    }

    /**
     * This interceptor will be called ONLY if the network is available
     *
     * @return
     */
    private static Interceptor networkInterceptor() {
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Log.d("rht", "network interceptor: called.");

                Response response = chain.proceed(chain.request());

                CacheControl cacheControl = new CacheControl.Builder()
                        .maxAge(5, TimeUnit.SECONDS)
                        .build();

                return response.newBuilder()
                        .removeHeader(HEADER_PRAGMA)
                        .removeHeader(HEADER_CACHE_CONTROL)
                        .header(HEADER_CACHE_CONTROL, cacheControl.toString())
                        .build();
            }
        };
    }

    private static HttpLoggingInterceptor httpLoggingInterceptor() {
        HttpLoggingInterceptor httpLoggingInterceptor =
                new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                    @Override
                    public void log(String message) {
                        Log.d("rht", "log: http log: " + message);
                    }
                });
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return httpLoggingInterceptor;
    }

    public static synchronized RHTRetroClient getInstance() {
        if (mInstance == null) {
            mInstance = new RHTRetroClient();
        }
        return mInstance;
    }

    public APIInterfaceProviderIMPL getAPIInterfaceProvider() {
        return retrofit.create(APIInterfaceProviderIMPL.class);
    }

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29891139

复制
相关文章
基于运动矢量重用的转码优化
 点击上方“LiveVideoStack”关注我们 ▲扫描图中二维码或点击阅读原文▲ 了解音视频技术大会更多信息 编者按:视频转码是视频相关领域中最重要的业务,需要消耗大量的算力。转码有解码和编码两个阶段,在编码中,运动矢量计算是消耗CPU算力最多的部分,因此要考虑如何减少大量的计算并提高图像质量。LiveVideoStack邀请到了英特尔的谢义老师,为我们介绍基于运动矢量重用的转码优化。 文/谢义 整理/LiveVideoStack 大家好!我是谢义,来自英特尔亚太研发有限公司。我们团队主要负责基于至强
LiveVideoStack
2023/02/23
4770
基于运动矢量重用的转码优化
结构体位域
  例如下列结构体内的变量使用了位域,占用空间只有1字节(8bit)。相对于不使用位域的缩少了3字节(24bit)的数据。
Qt君
2019/10/12
5140
C结构体位域
有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位。正是基于这种考虑,C语言又提供了一种叫做位域的数据结构。
CtrlX
2023/03/21
1770
C结构体位域
卫星互联网中的高轨卫星和低轨卫星是啥情况?
从全球网络覆盖面积来看,目前尚有80%以上的陆地区域和95%以上的海洋区域没有地面网络覆盖。非地面网络(NTN)是地面蜂窝通信技术的重要补充,是手机直连卫星的技术方向之一。
通往ICT之路
2024/04/24
3.2K0
卫星互联网中的高轨卫星和低轨卫星是啥情况?
基于Docker的FRP内网穿透部署
Power
2025/03/04
690
C结构体位域
有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可。例如开关只有通电和断电两种状态,用 0 和 1 表示足以,也就是用一个二进位。正是基于这种考虑,C语言又提供了一种叫做位域的数据结构。
CtrlX
2023/03/08
2660
C结构体位域
基于事件的光流矢量符号体系结构
Vector-Symbolic Architecture for Event-Based Optical Flow
CreateAMind
2024/07/05
1390
基于事件的光流矢量符号体系结构
基于Python的Tensorflow卫星数据分类神经网络
深度学习已经占据了解决复杂问题的大多数领域,地理空间领域也不例外。文章的标题让您感兴趣,因此希望熟悉卫星数据集 ; 目前,Landsat 5 TM。机器学习(ML)算法如何工作的知识很少,将帮助快速掌握这本动手教程。对于那些不熟悉ML概念的人,简而言之,它是建立一个实体的一些特征(特征或X)与其他属性(值或标签或Y)之间的关系 - 提供了大量的例子(标记数据) )到模型,以便从中学习,然后预测新数据(未标记数据)的值/标签。这对于机器学习来说已经足够理论了!
代码医生工作室
2019/09/16
3.3K0
基于Python的Tensorflow卫星数据分类神经网络
redis穿透 击穿_redis缓存穿透和雪崩
大家好,又见面了,我是你们的朋友全栈君。​ 1、redis雪崩、穿透、击穿的原因和解决方案 1)雪崩:多个key在某一时间同时失效,导致数据库压力过大 解决方案:不同的key设置不同的过期时间,尽量错开 2)穿透:在访问某个key时缓存中不存在,导致每次查询都会访问数据库 解决方案:第一次访问时如果key不存在,则在缓存中设置一个空值,并设置较短的过期时间 3)击穿:单个key缓存突然失效,这时大量的请求进行访问,导致数据压力过大 解决方案: 1、双重检索机制:某个key只让一个线程查询,阻塞其他线程
全栈程序员站长
2022/10/05
6010
Redis 的雪崩、穿透和击穿
  雪崩就是指缓存中大批量热点数据过期后系统涌入大量查询请求,因为大部分数据在Redis层已经失效,请求渗透到数据库层,大批量请求犹如洪水一般涌入,引起数据库压力造成查询堵塞甚至宕机。
码客说
2023/04/01
2830
一个基于 .NET 开源免费的异地组网和内网穿透工具
今天大姚给大家分享一个基于 .NET 开源免费的异地组网和内网穿透工具:linker。
追逐时光者
2025/03/28
1900
一个基于 .NET 开源免费的异地组网和内网穿透工具
3D矢量和6D矢量机器人建模的对比
基于6D矢量的机器人动力学是由学者Featherstone首先提出,并被机器人其他很多动力学建模软件广泛应用。包括开源机器人软件kdl.
ZC_Robot机器人技术
2020/10/24
3.3K3
3D矢量和6D矢量机器人建模的对比
位图图像和矢量图像
位图是由像素(Pixel)组成的,像素是位图最小的信息单元,存储在图像栅格中。 每个像素都具有特定的位置和颜色值。按从左到右、从上到下的顺序来记录图像中每一个像素的信息,如:像素在屏幕上的位置、像素的颜色等。位图图像质量是由单位长度内像素的多少来决定的。单位长度内像素越多,分辨率越高,图像的效果越好。位图也称为“位图图像”“点阵图像”“数据图像”“数码图像”。
用户7657330
2021/02/02
1K0
开发丨图像处理一定要用卷积神经网络?这里有一个另辟蹊径的方法
近年来,卷积神经网络(CNN)以其局部权值共享的特殊结构在语音识别和图像处理等方面得到了快速发展,特别是大型图像处理方面,更是表现出色,逐渐成为了行业内一个重要的技术选择。 不过,好用并不代表万能。这里 AI 科技评论从一个卫星图像分析的具体实例出发,介绍了CNN建模和本地拉普拉斯滤波这两种分析技术的效果对比,最终我们发现,本地拉普拉斯滤波的效果反而更好。 卷积神经网络 为了从卫星图像中分析和评估一项自然灾害造成的损失,首先需要得到相关地理区域实时的高分辨率的卫星图像,这是进行后续所有分析的数据基础。目
AI科技评论
2018/03/09
1.4K0
开发丨图像处理一定要用卷积神经网络?这里有一个另辟蹊径的方法
进展:基于Himawari-8卫星的云参数综合反演
云覆盖地球表面的三分之二以上,是地球-大气系统的重要组成部分。云参数反演的必要性体现在以下三个方面:①云是气候预测和模拟不确定性的重要来源;云对地球辐射收支的影响,取决于云顶高度(CTH)、云相态、云光学厚度(τ)和云顶粒子有效半径(Re)等物理参数。②在分析气溶胶-云-降水-气候相互作用,特别是城市化和人为气溶胶排放对海洋层积云、浅对流云和暖雨过程的影响时,CTH、τ和Re也是主要工具。③云相态、τ和Re是目前主要快速辐射传输模式(如CRTM、RTTOV)进行云内辐射传输模拟的基本参数;提供精确的云相态、τ和Re观测,是提高云区辐射资料同化的关键。
气象学家
2020/10/09
2.5K0
进展:基于Himawari-8卫星的云参数综合反演
位图和矢量图区别
位图和矢量图是计算机图形中的两大概念,这两种图形都被广泛应用到出版,印刷,互联网[如flash和svg]等各个方面,他们各有优缺点,两者各自的好处几乎是无法相互替代的,所以,长久以来,矢量跟位图在应用中一直是平分秋色。
全栈程序员站长
2022/09/20
1.2K0
ICCV 2021 Oral | 基于点云的类级别刚体与带关节物体位姿追踪
导读:本文是计算机视觉领域顶级会议 ICCV入选论文《基于点云的类级别刚体与带关节物体位姿追踪(CAPTRA: CAtegory-level Pose Tracking for Rigid and Articulated Objects from Point Clouds)》的解读。该工作由北京大学前沿计算研究中心陈宝权课题组与斯坦福大学/北京大学王鹤等合作完成,论文共同一作翁伊嘉为2021届图灵班学生。
AI科技评论
2021/09/16
5550
泛广电领域的卫星传输和公网传输
大家好,我是来自安徽广播电视台的张博力,接下来我将为大家详细介绍泛广电领域的卫星传输和公网传输。
LiveVideoStack
2019/11/13
9390
泛广电领域的卫星传输和公网传输
基于TensorFlow的循环神经网络生成矢量格式的伪造汉字
注意:对于中文汉字和日文汉字我根据具体情况交替使用它们。
花落花飞去
2018/02/08
2.8K0
基于TensorFlow的循环神经网络生成矢量格式的伪造汉字
基于HT for Web矢量实现2D叶轮旋转
之前在拓扑上的应用都是些静态的图元,今天我们将在拓扑上设计一个会动的图元——叶轮旋转。 我们先来看下这个叶轮模型长什么样 从模型上看,这个叶轮模型有三个叶片,每一个叶片都是不规则图形,显然无法用上我们
HT for Web
2018/01/03
7760
基于HT for Web矢量实现2D叶轮旋转

相似问题

统一更改GameObject颜色(c#)

25

GameObject不包含TryGetComponet的def?统一

13

统一GameObject速度与动画问题

12

网络凸轮的统一许可

12

C#统一-识别影响GameObject的方法

23
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档