2013-05-27 9 views
48
public class CustomRequest extends JsonObjectRequest { 

    public CustomRequest(String url, JSONObject params, 
      Listener<JSONObject> listener, ErrorListener errorListener) 
      throws JSONException { 
     super(Method.POST,url, params, listener, 
       errorListener); 
     this.setShouldCache(Boolean.TRUE); 
    } 
} 

このコードを使用すると、暗黙的に応答をキャッシュすることができます。私は、要求が送信されるという仮定の下にあったので、私は、それが動作するかどうかはわからない:Android Volley + JSONObjectRequestキャッシング

  1. それが最初のキャッシュにヒットし、

  2. をonresponseすることを送信し、その後場合の結果それはonresponseにそれを提供するリモートサーバーから通ってくる

アップデート:私は手動でキャッシュを取得し、それiを再構築する方法を考え出し

JSONObjectをOnResponse関数を介して送信しますが、暗黙のキャッシングがあると考えると効率的ではないようです。 JsonObjectRequestクラスは、未処理の応答データではなく、キャッシュされたエントリとしてJSONObjectを返します。

しかし、私はまだ間違いをしているかどうか知りたいです。

あいまいさはドキュメントの不足によるものなので、私が何か非常に明白なものを紛失している場合は謝罪します。

答えて

86

この回答を参照してください - Set expiration policy for cache using Google's Volley

これは、バレーボールはヘッダのみ「のCache-Control」に基づいて応答をキャッシュするかどうかを決定し、その後、「有効期限」「MAXAGE」を意味します。あなたは何ができるか

この方法 com.android.volley.toolbox.HttpHeaderParser.parseCacheHeaders(NetworkResponse response) を変更し、これらのヘッダを無視している、あなたのために働くとあなたのリクエストクラスであなたのメソッドを使用してどのような値にentry.softTtlentry.ttlフィールドを設定します。次に例を示します。このようなあなたのリクエストクラスで

/** 
* Extracts a {@link Cache.Entry} from a {@link NetworkResponse}. 
* Cache-control headers are ignored. SoftTtl == 3 mins, ttl == 24 hours. 
* @param response The network response to parse headers from 
* @return a cache entry for the given response, or null if the response is not cacheable. 
*/ 
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; 
} 

このメソッドを使用する:

public class MyRequest extends com.android.volley.Request<MyResponse> { 

    ... 

    @Override 
    protected Response<MyResponse> parseNetworkResponse(NetworkResponse response) { 
     String jsonString = new String(response.data); 
     MyResponse MyResponse = gson.fromJson(jsonString, MyResponse.class); 
     return Response.success(MyResponse, HttpHeaderParser.parseIgnoreCacheHeaders(response)); 
    } 

} 
+1

これは、キャッシュがonDestroyを超えて続くことを意味しますか?次回にアプリケーションを作成すると、キャッシュからフェッチされます。 – gaara87

+3

はい、キャッシュはメモリだけでなくディスクにも保存されます(詳細はDiskBasedCacheクラスを参照)。クイックテストとして、データを読み込んでからアプリを終了し、wifiや3gをオフにしてアプリをもう一度入力してください。 mMaxCacheSizeInBytesフィールドにキャッシュサイズを指定することもできます。 –

+2

はい、私はアプリにいる間キャッシュしますが、アプリを終了してアプリに戻ると、キャッシュからフェッチするとnullが返されました。したがって、活動のライフサイクルの間にそれが存在するかどうかの問題です。 – gaara87

5

oleksandr_yefremovは場合は特に、あなたがAndroidのバレーボールのキャッシュ戦略を扱うときにあなたを助けることができる優れたコードを提供REST APIに不適切な「Cache-Control」ヘッダーがある場合や、独自のアプリキャッシュ戦略をさらに制御したい場合

キーはHttpHeaderParser.parseCacheHeaders(NetworkResponse response))です。独自のキャッシュ戦略を使用したい場合。対応するクラスのparseIgnoreCacheHeaders(NetworkResponse response)に置き換えてください。あなたのクラスがJsonObjectRequestを拡張する場合、またJsonObjectRequestに移動し、

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

を見つけ、oleksandr_yefremovとskyfishjyためHttpHeaderParser.parseIgnoreCacheHeaders

+0

'NetworkImageView'でそれをどうしようもできますか? – fiddler

2

+1でHttpHeaderParser.parseCacheHeaders(response)を置き換える

、ここでJSONに適した具体的な、再利用可能なクラスを提供またはその他の文字列ベースのAPI:

public class CachingStringRequest extends StringRequest { 
    public CachingStringRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener) { 
     super(method, url, listener, errorListener); 
    } 

    public CachingStringRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener) { 
     super(url, listener, errorListener); 
    } 

    @Override 
    protected Response<String> parseNetworkResponse(NetworkResponse response) { 
     String parsed; 
     try { 
      parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); 
     } catch (UnsupportedEncodingException e) { 
      parsed = new String(response.data); 
     } 
     return Response.success(parsed, parseIgnoreCacheHeaders(response)); 
    } 
} 

ここで、関数parseIgnoreCacheHeaders()com上記のoleksandr_yefremovの答えから。結果のjsonが3分(ライブ)と24時間(期限切れだが利用可能なまま)キャッシュすることができる場所であれば、どこでもCachingStringRequestクラスを使用します。サンプル要求:

CachingStringRequest stringRequest = new CachingStringRequest(MY_API_URL, callback); 

コールバックオブジェクトのonResponse()関数内で、jsonを解析します。必要なキャッシング制限を設定します。リクエストごとにカスタムの有効期限を追加するためにパラメータ化できます。

jsonをダウンロードし、ダウンロードした情報をレンダリングする簡単なアプリでこれを試してみてください。キャッシュが最初に正常にダウンロードされたら、キャッシュがライブ中にオリエンテーションを変更しながらスピーディーなレンダリングを見てください(ライブキャッシュヒットではダウンロードは発生しません)。今度はアプリを終了し、そのキャッシュヒットが期限切れになるまで3分待ってください(キャッシュから削除されるまでに24時間かかることはありません)。飛行機モードを有効にしてアプリを再起動してください。 Volleyエラーコールバックが発生し、キャッシュされたデータから「成功した」onResponse()コールバックが発生し、コンテンツをレンダリングし、期限切れのキャッシュから来たことを知らせる/警告することができます。

この種類のキャッシングを使用すると、ローダーや方向変更を処理する他の手段を取り除くことができます。リクエストがVolleyシングルトンを通過し、結果がキャッシュされると、方向変更によって発生するリフレッシュは、Loaderなしで自動的にVolleyによってキャッシュからレンダリングされます。

もちろん、これはすべての要件に適合しません。 YMMV

0

私はVolleyにStringRequestを拡張して強制的にすべての応答をキャッシュに入れ、強制的にキャッシュしたい要求をCachingStringRequestに置き換えました。

オーバーライドされたメソッドparseNetworkResponse私はCache-Controlヘッダーを削除します。この方法で、Volleyはそのキャッシュ内にレスポンスを永続させています。

関連する問題