2014-09-04 29 views
2

我已經添加了針對獲取Json對象的請求,如果wifi已打開,則需要數據,但在離線模式下無法訪問,即使緩存啓用了請求。Android:Volley不能在離線狀態下使用緩存

我做下面的代碼

public class VolleySingleton extends Application 
{ 
    public static final String TAG = VolleySingleton.class.getSimpleName(); 
    private RequestQueue mRequestQueue; 
    private static VolleySingleton mInstance; 
    private ImageLoader mImageLoader; 
    private final String DEFAULT_CACHE_DIR = "sl_cache"; 

    @Override 
    public void onConfigurationChanged(Configuration newConfig) 
    { 
     super.onConfigurationChanged(newConfig); 
    } 

    @Override 
    public void onCreate() 
    { 
     super.onCreate(); 
     mInstance = this; 
    } 

    public static synchronized VolleySingleton getInstance() 
    { 
     return mInstance; 
    } 

    public ImageLoader getImageLoader() 
    { 
     getRequestQueue(); 
     if (mImageLoader == null) 
     { 
      mImageLoader = new ImageLoader(this.mRequestQueue, new LruBitmapCache()); 
     } 
     return this.mImageLoader; 
    } 

    public <T> void addToRequestQueue(Request<T> req, String tag) 
    { 
     // set the default tag if tag is empty 
     req.setTag(TextUtils.isEmpty(tag) ? TAG : tag); 
     getRequestQueue().add(req); 
    } 

    public <T> void addToRequestQueue(Request<T> req) 
    { 
     req.setTag(TAG); 
     getRequestQueue().add(req); 
    } 

    public void cancelPendingRequests(Object tag) 
    { 
     if (mRequestQueue != null) 
     { 
      mRequestQueue.cancelAll(tag); 
     } 
    } 

    public RequestQueue getRequestQueue() 
    { 
     if (mRequestQueue == null) 
     { 
      Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024 * 10); // 10MB cap 
      Network network = new BasicNetwork(new HurlStack()); 
      mRequestQueue = new RequestQueue(cache, network); 
      mRequestQueue.start(); 
     } 
     return mRequestQueue; 
    } 
} 


private void getData(String url, String tag) 
{ 
      final JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() 
      { 
       @Override 
       public void onResponse(JSONObject response) 
       { 
        Log.wtf("HOME", response.toString()); 
        String result = parseData(response.toString()); 
        postProcessing(result); 
        //SocialLadder.getInstance().getRequestQueue().getCache().invalidate(url, true); 
       } 


      }, new Response.ErrorListener() 
      { 
       @Override 
       public void onErrorResponse(VolleyError error) 
       { 
        VolleyLog.wtf("HOME", "Error: " + error.getMessage()); 
        stopRefresher(); 
       } 
      }) 
      { 
       @Override 
       protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) 
       {       
        try 
        { 
         String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); 
         return !jsonString.isEmpty() ? Response.success(new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response)) : Response.success(new JSONObject(), HttpHeaderParser.parseCacheHeaders(response)); 
        } 
        catch (JSONException ex) 
        { 
         ex.printStackTrace(); 
        } 
        catch (UnsupportedEncodingException e) 
        { 
         e.printStackTrace(); 
        } 
        return null; 
       } 
      }; 
      jsonObjReq.setShouldCache(true); 
      VolleySingleton.getInstance().addToRequestQueue(jsonObjReq, tag); 
} 

請幫幫忙,我想我的緩存畫面數據。

編輯

緩存數據

private String getCache(String url) 
    { 
     String data = ""; 
     Cache cache = VolleySingleton.getInstance().getRequestQueue().getCache(); 
     Cache.Entry entry = cache.get(url); 
     if (entry != null) 
     { 
      try 
      { 
       data = new String(entry.data, "UTF-8"); 
       // handle data, like converting it to xml, json, bitmap etc., 
      } 
      catch (UnsupportedEncodingException e) 
      { 
       e.printStackTrace(); 
      } 
     } 
     /*else 
     { 
      // Cached response doesn't exists. Make network call here 
     }*/ 
     return data; 
    } 
+0

哪裏是您的離線查看代碼? – mmlooloo 2014-09-04 12:23:46

+0

@mmlooloo我更新了代碼 – 2014-09-04 12:41:47

回答

5

爲了與你需要有兩件事情Volley緩存內容:

1)服務器,可以緩存它。它通常出現在cache control tagHTTP header中。

2)你保存它或在這種情況下,你告訴Volly保存。

所以我認爲你的問題是在第一。這意味着服務器劑量不允許緩存這些文件,以確認我的答案,你可以做這些事情之一:

  1. 下載該插件(RESTClient實現)爲mozilla和發送您的請求,並檢查頭文件進行緩存控制。如果服務器劑量不會允許你緩存你會看到類似下面的圖片,notice cache control tag

enter image description here

  • 設定破壞在headerValue = headers.get("Cache-Control");HttpHeaderParse類,看看怎麼回事當Volley想解析cache control tag
  • +0

    我已經檢查了標題,緩存控制從響應是沒有chache。這意味着我無法緩存? – 2014-09-04 13:19:10

    +0

    是的,這意味着Volley不會緩存它,您可以更改源代碼,也可以手動將其緩存,並將其插入到'onResponse'回調中的Volley緩存中。 – mmlooloo 2014-09-04 13:22:50

    +0

    你能分享一些鏈接來解釋如何手動緩存嗎? – Gaurav 2016-11-22 13:37:07

    5

    就在** BasicNetwork *類中添加這一行或修改如下

    @Override 
        public NetworkResponse performRequest(Request<?> request) throws VolleyError { 
        long requestStart = SystemClock.elapsedRealtime(); 
        while (true) { 
    
         HttpResponse httpResponse = null; 
         byte[] responseContents = null; 
         Map<String, String> responseHeaders = Collections.emptyMap(); 
         try { 
         if(!ConnectivityUtils.isNetworkEnabled(BBApplication.getContext())) { 
           return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, 
             request.getCacheEntry().data, responseHeaders, true); 
          } 
    
          // Gather headers. 
          Map<String, String> headers = new HashMap<String, String>(); 
          addCacheHeaders(headers, request.getCacheEntry()); 
          httpResponse = mHttpStack.performRequest(request, headers); 
          StatusLine statusLine = httpResponse.getStatusLine(); 
          int statusCode = statusLine.getStatusCode(); 
          responseHeaders = convertHeaders(httpResponse.getAllHeaders()); 
          // Handle cache validation. 
    
    
          if (statusCode == HttpStatus.SC_NOT_MODIFIED) { 
           Cache.Entry entry = request.getCacheEntry(); 
    
           if (entry == null) { 
            return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, null, responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); 
           } 
    
           // A HTTP 304 response does not have all header fields. We 
           // have to use the header fields from the cache entry plus 
           // the new ones from the response. 
           // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5 
           entry.responseHeaders.putAll(responseHeaders); 
           return new NetworkResponse(HttpStatus.SC_NOT_MODIFIED, entry.data, entry.responseHeaders, true, SystemClock.elapsedRealtime() - requestStart); 
          } 
          // Some responses such as 204s do not have content. We must check. 
          if (httpResponse.getEntity() != null) { 
           responseContents = entityToBytes(httpResponse.getEntity()); 
          } else { 
           // Add 0 byte response as a way of honestly representing a 
           // no-content request. 
           responseContents = new byte[0]; 
          } 
    
          // if the request is slow, log it. 
          long requestLifetime = SystemClock.elapsedRealtime() - requestStart; 
          logSlowRequests(requestLifetime, request, responseContents, statusLine); 
    
          if (statusCode < 200 || statusCode > 299) { 
           throw new IOException(); 
          } 
          return new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart); 
         } catch (SocketTimeoutException e) { 
          attemptRetryOnException("socket", request, new TimeoutError()); 
         } catch (ConnectTimeoutException e) { 
          attemptRetryOnException("connection", request, new TimeoutError()); 
         } catch (NoHttpResponseException e) { 
          attemptRetryOnException("socket", request, new TimeoutError()); 
         } catch (UnknownHostException e) { 
          attemptRetryOnException("socket", request, new TimeoutError()); 
         } catch (MalformedURLException e) { 
          throw new RuntimeException("Bad URL " + request.getUrl(), e); 
         } catch (IOException e) { 
          int statusCode = 0; 
          NetworkResponse networkResponse = null; 
          if (httpResponse != null) { 
           statusCode = httpResponse.getStatusLine().getStatusCode(); 
          } else { 
           throw new NoConnectionError(e); 
          } 
          VolleyLog.e("Unexpected response code %d for %s", statusCode, request.getUrl()); 
          if (responseContents != null) { 
           networkResponse = new NetworkResponse(statusCode, responseContents, responseHeaders, false, SystemClock.elapsedRealtime() - requestStart); 
           if (statusCode == HttpStatus.SC_UNAUTHORIZED || statusCode == HttpStatus.SC_FORBIDDEN) { 
            attemptRetryOnException("auth", request, new AuthFailureError(networkResponse)); 
           } else { 
            // TODO: Only throw ServerError for 5xx status codes. 
            throw new ServerError(networkResponse); 
           } 
          } else { 
           throw new NetworkError(networkResponse); 
          } 
         } 
        } 
    } 
    

    和數據請求到期,您可以使用使用改變Cached.Entry自己HttpHeaderParser

    點擊代碼BasicNetwork

    這段代碼是做什麼的,它將檢查互聯網連接和網絡調用,如果它有緩存副本則恢復。

    注意API響應應該是可緩存的,因爲如果響應頭允許,Volley只緩存數據。 See here for Cached Control Header

    +0

    該怎麼做..? – 2016-02-29 09:50:11

    +0

    @RishabhSrivastava您必須將抽象代碼作爲模塊與您一起使用,或者擴展BasicNetwork類並覆蓋上面的代碼。 – 2016-04-08 09:11:14