我正在使用volly来完美地检索数据及其工作,除了我的json数组没有存储在缓存中.

这是我的代码:

private void getCacheValue() {
    Cache cache = AppController.getInstance().getRequestQueue().getCache();
    Cache.Entry entry = cache.get(Endpoints.product_url);


    if(entry != null){
        Log.w("Logdata:",""+ entry.toString());
        try {
            String data = new String(entry.data,"UTF-8");
            JSONArray jsonArray = new JSONArray(data);

            // handle data,like converting it to xml,json,bitmap etc.,Log.v("Hello",data);
            listProduct.clear();
            for (int i = 0; i < jsonArray.length(); i++) {
                try {
                    JSONObject object = jsonArray.getJSONObject(i);
                    ItemCategories image = new ItemCategories();
                    image.setCategoryItem(object.getString(key_title));
                    image.setUrlThumb(object.getString(key_image));

                    listProduct.add(image);
                    } catch (JSONException e) {
                        Log.e(TAG,"Json parsing error: " + e.getMessage());
                    }
                }

                adapterProductList.notifyDataSetChanged();
                progressBarMain.setVisibility(View.GONE);
                internetError.setVisibility(View.GONE);
                recycleProductList.setVisibility(View.VISIBLE);

            } catch (UnsupportedEncodingException e) {
                e.printstacktrace();
            } catch (JSONException e) {
                e.printstacktrace();
                Log.v("JSON EXCEPTION","DECLINE");
            }
    } else {
        if(isNetworkAvailable()) {
            fetchImages();
        } else {
            progressBarMain.setVisibility(View.GONE);
            internetError.setVisibility(View.VISIBLE);
        }
    }
}

private void fetchImages() {
    JsonObjectRequest jsObjRequest = 
        new JsonObjectRequest(Request.Method.GET,Endpoints.product_url(String) null,new Response.Listener<JSONObject>() {    
                @Override
                public void onResponse(JSONObject response) {
                    listProduct.clear();
                    try {
                        JSONArray routes = response.getJSONArray(key_product);
                        for (int i = 0; i < routes.length(); i++) {
                            JSONObject object = routes.getJSONObject(i);
                            ItemCategories categories = new ItemCategories();
                            categories.setCategoryItem(object.getString(key_title));
                            categories.setUrlThumb(object.getString(key_image)); 

                            listProduct.add(categories);
                        }
                        adapterProductList.notifyDataSetChanged();
                        progressBarMain.setVisibility(View.GONE);
                        internetError.setVisibility(View.GONE);
                        recycleProductList.setVisibility(View.VISIBLE);
                        } catch (JSONException e) {
                            e.printstacktrace();
                            Toast.makeText(getApplicationContext(),"Error: " + e.getMessage(),Toast.LENGTH_LONG).show();
                         }
                     }
                  },new Response.ErrorListener() {
                      @Override
                      public void onErrorResponse(VolleyError error) {
                          VolleyLog.d(TAG,"Error: " + error.getMessage());
                      }
                  });
    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(jsObjRequest);
}

我已经在清单中声明了Appcontroller,但我不知道为什么缓存不起作用.

这是我的json_data

fetchImage()正在运行,因为recyclerview中有数据.但是,当我尝试脱机检索数据时,它会显示任何数据,因为我的缓存无法存储任何数据.

解决方法

默认情况下,如果响应标头允许,Volley仅缓存数据.
Volley根据以下响应标头缓存响应:
1.缓存控制
2.到期
3. maxAge

请参阅以下功能了解详情:

public static Cache.Entry parseCacheHeaders(NetworkResponse response) {
    long Now = System.currentTimeMillis();

    Map<String,String> headers = response.headers;

    long serverDate = 0;
    long lastModified = 0;
    long serverExpires = 0;
    long softExpire = 0;
    long finalExpire = 0;
    long maxAge = 0;
    long staleWhileRevalidate = 0;
    boolean hasCacheControl = false;
    boolean mustRevalidate = false;

    String serverEtag = null;
    String headerValue;

    headerValue = headers.get("Date");
    if (headerValue != null) {
        serverDate = parseDateAsEpoch(headerValue);
    }

    headerValue = headers.get("Cache-Control");
    if (headerValue != null) {
        hasCacheControl = true;
        String[] tokens = headerValue.split(",");
        for (int i = 0; i < tokens.length; i++) {
            String token = tokens[i].trim();
            if (token.equals("no-cache") || token.equals("no-store")) {
                return null;
            } else if (token.startsWith("max-age=")) {
                try {
                    maxAge = Long.parseLong(token.substring(8));
                } catch (Exception e) {
                }
            } else if (token.startsWith("stale-while-revalidate=")) {
                try {
                    staleWhileRevalidate = Long.parseLong(token.substring(23));
                } catch (Exception e) {
                }
            } else if (token.equals("must-revalidate") || token.equals("proxy-revalidate")) {
                mustRevalidate = true;
            }
        }
    }

    headerValue = headers.get("Expires");
    if (headerValue != null) {
        serverExpires = parseDateAsEpoch(headerValue);
    }

    headerValue = headers.get("Last-Modified");
    if (headerValue != null) {
        lastModified = parseDateAsEpoch(headerValue);
    }

    serverEtag = headers.get("ETag");

    // Cache-Control takes precedence over an Expires header,even if both exist and Expires
    // is more restrictive.
    if (hasCacheControl) {
        softExpire = Now + maxAge * 1000;
        finalExpire = mustRevalidate
                ? softExpire
                : softExpire + staleWhileRevalidate * 1000;
    } else if (serverDate > 0 && serverExpires >= serverDate) {
        // Default semantic for Expire header in HTTP specification is softExpire.
        softExpire = Now + (serverExpires - serverDate);
        finalExpire = softExpire;
    }

    Cache.Entry entry = new Cache.Entry();
    entry.data = response.data;
    entry.etag = serverEtag;
    entry.softTtl = softExpire;
    entry.ttl = finalExpire;
    entry.serverDate = serverDate;
    entry.lastModified = lastModified;
    entry.responseHeaders = headers;

    return entry;
}

您可以通过覆盖Request对象来更改默认缓存策略.
您可以覆盖JsonObjectRequest,如:

public class CustomJsonObjectRequest extends JsonObjectRequest {
    public CustomJsonObjectRequest(int method,String url,JSONObject jsonRequest,Response.Listener<JSONObject> listener,Response.ErrorListener errorListener) {
        super(method,url,jsonRequest,listener,errorListener);
    }

    public CustomJsonObjectRequest(String url,Response.ErrorListener errorListener) {
        super(url,errorListener);
    }

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,HttpHeaderParser.parseCharset(response.headers,PROTOCOL_CHARSET));
            return Response.success(new JSONObject(jsonString),parseIgnoreCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
        }
    }

    public static Cache.Entry parseIgnoreCacheHeaders(NetworkResponse response) {
        long Now = System.currentTimeMillis();
        Map<String,String> headers = response.headers;
        long serverDate = 0;
        String serverEtag = null;
        String headerValue;

        headerValue = headers.get("Date");
        if (headerValue != null) {
            serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
        }

        serverEtag = headers.get("ETag");

        final long cacheHitButRefreshed = 3 * 60 * 1000; // in 3 minutes cache will be hit,but also refreshed on background
        final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
        final long softExpire = Now + cacheHitButRefreshed;
        final long ttl = Now + cacheExpired;

        Cache.Entry entry = new Cache.Entry();
        entry.data = response.data;
        entry.etag = serverEtag;
        entry.softTtl = softExpire;
        entry.ttl = ttl;
        entry.serverDate = serverDate;
        entry.responseHeaders = headers;

        return entry;
    }
}

将fetchImage函数更新为:

private void fetchImages() {

    CustomJsonObjectRequest jsObjRequest = new CustomJsonObjectRequest()
            (Request.Method.GET,Endpoints.product_url,(String) null,new Response.Listener<JSONObject>() {

                @Override
                public void onResponse(JSONObject response) {
                    listProduct.clear();
                    try {
                        JSONArray routes = response.getJSONArray(key_product);
                        for (int i = 0; i < routes.length(); i++) {
                            JSONObject object = routes.getJSONObject(i);
                            ItemCategories categories = new ItemCategories();

                            categories.setCategoryItem(object.getString(key_title));
                            categories.setUrlThumb(object.getString(key_image));

                            listProduct.add(categories);
                        }
                        adapterProductList.notifyDataSetChanged();
                        progressBarMain.setVisibility(View.GONE);
                        internetError.setVisibility(View.GONE);
                        recycleProductList.setVisibility(View.VISIBLE);
                    } catch (JSONException e) {
                        e.printstacktrace();
                        Toast.makeText(getApplicationContext(),Toast.LENGTH_LONG).show();
                    }
                }
            },new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    VolleyLog.d(TAG,"Error: " + error.getMessage());

                }
            });
    // Adding request to request queue
    AppController.getInstance().addToRequestQueue(jsObjRequest);
}

作为参考,请检查Android Volley + JSONObjectRequest Caching

android – Cache.Entry没有获取json数据的更多相关文章

  1. 关于h5中的fetch方法解读(小结)

    这篇文章主要介绍了关于h5中的fetch方法解读(小结),fetch身为H5中的一个新对象,他的诞生,是为了取代ajax的存在而出现,有兴趣的可以了解一下

  2. ios – 使用NSURLSession获取JSON数据

    我试图从谷歌距离api使用NSURLSession获取数据,但如下所示,当我打印响应和数据时,我得到的结果为NULL.可能是什么问题?

  3. ios – 错误域= com.alamofire.error.serialization.response代码= -1011“请求失败:禁止

    任何人都可以帮我解决以下错误–>在AFNetworking2.5中使用“删除”方法时出错解决方法我发现,如果我的手机时钟不同步……它不允许我更新…也许检查你的手机设置到正确的时间“自动区”,看看是否有效…

  4. iOS网页/原生应用Facebook登录弹出 – 失败?

    如果我重新启动app/web-app,用户将自动登录,并重定向到成功页面.我认为是导致问题的原因当您在Firefox/Chrome/Safari浏览器中运行网页时,Facebook登录对话框会弹出一个弹出窗口或另一个选项卡.我相信这是这个弹出页面的一个问题,以及当成功登录时Javascript如何与自身通信.window.close的东西没有返回的根页面…失败的解决方法由于应用程序挂在前面提到的URL上,我决定在shouldStartLoadWithRequest(…)中添加if语句以强制UIWebvie

  5. ios – Watchkit新会话不起作用

    我的手表扩展中有两个视图控制器.每当我打电话时我只得到第一个视图控制器的响应,并在第二个viewcontroller中得到错误WCSession在app和watch扩展中启动.任何建议?

  6. 使用Firebase iOS Swift将特定设备的通知推送到特定设备

    我非常感谢PushNotifications的帮助.我的应用聊天,用户可以直接向对方发送短信.但是如果没有PushNotifications,它就没有多大意义.它全部设置在Firebase上.如何将推送通知从特定设备发送到特定设备?

  7. ios – 保存从查询中获取的用户的属性(即不在currentUser上)

    我有兴趣根据currentUser执行的操作将属性保存到数据库中的用户.基于以下代码,我收到错误消息“除非已通过logIn或signUp验证用户,否则无法保存用户”我想知道是否有一个解决方法,我可以将属性保存到foundUser,而无需登录该用户.谢谢你的帮助!解决方法如果要更新当前不是登录用户的用户,则需要使用主密钥调用Parse.您可以从CloudCode执行此操作;并从您的iOS项目中调用它;

  8. 在iOS中使用NSJSONSerialization进行JSON解析

    解决方法首先在您的JSON响应字典中,在“RESPONSE”键下,您有一个数组而不是字典,该数组包含字典对象.所以要提取用户名和电子邮件ID,如下所示

  9. Xcode:Alamofire获得String响应

    我是IOS开发的新手,目前正在与Alamofire学习网络我正在尝试登录…每当凭证正确时,.PHP文件返回一个json,我可以通过以下代码从Alamofire获取json:现在……当凭证错误时,.PHP不会给json..而且它返回一个字符串..例如“wrong_password”或“userLocked”等等……如何通过Alamofire获得String响应?解决方法如果您希望JSON响应使用.responseJSON,如果您想要String响应,请使用.responseString.如果你想两者同时使用

  10. ios – 全局变量中的Appdelegate in swift

    我将一些数据从viewcontroller&从另一个视图控制器获取它.下面是应用程序委托的代码代码设置mainDic代码来获取字典.问题是我得到的输出没有.请让我正确.解决方法这是你的错误尝试将您的代码更改为此

随机推荐

  1. bluetooth-lowenergy – Altbeacon库无法在Android 5.0上运行

    昨天我在Nexus4上获得了Android5.0的更新,并且altbeacon库停止了检测信标.似乎在监视和测距时,didEnterRegion和didRangeBeaconsInRegion都没有被调用.即使RadiusNetworks的Locate应用程序现在表现不同,一旦检测到信标的值,它们就不再得到更新,并且通常看起来好像信标超出了范围.我注意到的一点是,现在在logcat中出现以下行“B

  2. android – react-native动态更改响应者

    我正在使用react-native进行Android开发.我有一个视图,如果用户长按,我想显示一个可以拖动的动画视图.我可以使用PanResponder实现这一点,它工作正常.但我想要做的是当用户长按时,用户应该能够继续相同的触摸/按下并拖动新显示的Animated.View.如果您熟悉Google云端硬盘应用,则它具有类似的功能.当用户长按列表中的任何项目时,它会显示可拖动的项目.用户可以直接拖

  3. android – 是否有可能通过使用与最初使用的证书不同的证书对其进行签名来发布更新的应用程序

    是否可以通过使用与最初使用的证书不同的证书进行签名来发布Android应用程序的更新?我知道当我们尝试将这样的构建上传到市场时,它通常会给出错误消息.但有没有任何出路,比如将其标记为主要版本,指定市场中的某个地方?解决方法不,你不能这样做.证书是一种工具,可确保您是首次上传应用程序的人.所以总是备份密钥库!

  4. 如何检测Android中是否存在麦克风?

    ..所以我想在让用户访问语音输入功能之前检测麦克风是否存在.如何检测设备上是否有麦克风.谢谢.解决方法AndroidAPI参考:hasSystemFeature

  5. Android – 调用GONE然后VISIBLE使视图显示在错误的位置

    我有两个视图,A和B,视图A在视图B上方.当我以编程方式将视图A设置为GONE时,它将消失,并且它正下方的视图将转到视图A的位置.但是,当我再次将相同的视图设置为VISIBLE时,它会在视图B上显示.我不希望这样.我希望视图B回到原来的位置,这是我认为会发生的事情.我怎样才能做到这一点?编辑–代码}这里是XML:解决方法您可以尝试将两个视图放在RelativeLayout中并相对于彼此设置它们的位置.

  6. android – 获得一首歌的流派

    我如何阅读与歌曲相关的流派?我可以读这首歌,但是如何抓住这首歌的流派,它存放在哪里?解决方法检查此代码:

  7. android – 使用textShadow折叠工具栏

    我有一个折叠工具栏的问题,在展开状态我想在文本下面有一个模糊的阴影,我使用这段代码:用:我可以更改textColor,它可以工作,但阴影不起作用.我为阴影尝试了很多不同的值.是否可以为折叠文本投射阴影?

  8. android – 重用arm共享库

    我已经建立了armarm共享库.我有兴趣重用一个函数.我想调用该函数并获得返回值.有可能做这样的事吗?我没有任何头文件.我试过这个Android.mk,我把libtest.so放在/jni和/libs/armeabi,/lib/armeabi中.此时我的cpp文件编译,但现在是什么?我从objdump知道它的名字编辑:我试图用这个android.mk从hello-jni示例中添加prebuild库:它工作,但libtest.so相同的代码显示以下错误(启动时)libtest.so存在于libhello-j

  9. android – 为NumberPicker捕获键盘’Done’

    我有一个AlertDialog只有一些文本,一个NumberPicker,一个OK和一个取消.(我知道,这个对话框还没有做它应该保留暂停和恢复状态的事情.)我想在软键盘或其他IME上执行“完成”操作来关闭对话框,就像按下了“OK”一样,因为只有一个小部件可以编辑.看起来处理IME“Done”的最佳方法通常是在TextView上使用setonEditorActionListener.但我没有任何Te

  10. android – 想要在调用WebChromeClient#onCreateWindow时知道目标URL

    当我点击一个带有target=“_blank”属性的超链接时,会调用WebChromeClient#onCreateWindow,但我找不到新的窗口将打开的新方法?主页url是我唯一能知道的东西?我想根据目标网址更改应用行为.任何帮助表示赞赏,谢谢!

返回
顶部