Volley de configuración de Android para usar desde caché

Estoy intentando crear y utilizar un escondrijo para una respuesta del servidor JSON.

Por ejemplo:

Caché JSON objetos a la memoria interna y el uso que cuando no tenemos una conexión a Internet.

En el siguiente código de ejemplo, no puedo encontrar ningún documento acerca de cómo almacenarlo en caché con Volley y reutilizarlo cuando el encabezado del servidor para la actualización no caduque.

De esta forma: establece la caducidad en el encabezado y utiliza caché e intenta cargar de nuevo después de la caducidad.

Estoy tratando de configurar el mecanismo de caché para este método:

 private void makeJsonArryReq() { JsonArrayRequest req = new JsonArrayRequest(Const.URL_JSON_ARRAY, new Response.Listener<JSONArray>() { @Override public void onResponse(JSONArray response) { msgResponse.setText(response.toString()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }); AppController.getInstance().addToRequestQueue(req,tag_json_arry); } 

Método de caché:

 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; } 

2 Solutions collect form web for “Volley de configuración de Android para usar desde caché”

Tenga en cuenta que si el servicio web admite la salida de almacenamiento en caché, no tendrá que utilizar CacheRequest continuación, porque Volley se almacenará automáticamente en caché.


Para su problema, utilizo algunos códigos dentro de parseCacheHeaders (y parseCacheHeaders códigos de @ oleksandr_yefremov ). El código siguiente que he probado. Por supuesto, puede utilizar para JsonArrayRequest también. ¡Espero que esto ayude!

  JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(0, mUrl, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { try { mTextView.setText(response.toString(5)); } catch (JSONException e) { mTextView.setText(e.toString()); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { } }) { @Override protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) { try { Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response); if (cacheEntry == null) { cacheEntry = new Cache.Entry(); } 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 long now = System.currentTimeMillis(); final long softExpire = now + cacheHitButRefreshed; final long ttl = now + cacheExpired; cacheEntry.data = response.data; cacheEntry.softTtl = softExpire; cacheEntry.ttl = ttl; String headerValue; headerValue = response.headers.get("Date"); if (headerValue != null) { cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue); } headerValue = response.headers.get("Last-Modified"); if (headerValue != null) { cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue); } cacheEntry.responseHeaders = response.headers; final String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); return Response.success(new JSONObject(jsonString), cacheEntry); } catch (UnsupportedEncodingException e) { return Response.error(new ParseError(e)); } catch (JSONException e) { return Response.error(new ParseError(e)); } } @Override protected void deliverResponse(JSONObject response) { super.deliverResponse(response); } @Override public void deliverError(VolleyError error) { super.deliverError(error); } @Override protected VolleyError parseNetworkError(VolleyError volleyError) { return super.parseNetworkError(volleyError); } }; MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest); 

ACTUALIZACIÓN :

Si desea una clase base, consulte los siguientes códigos:

 public class CacheRequest extends Request<NetworkResponse> { private final Response.Listener<NetworkResponse> mListener; private final Response.ErrorListener mErrorListener; public CacheRequest(int method, String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) { super(method, url, errorListener); this.mListener = listener; this.mErrorListener = errorListener; } @Override protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) { Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response); if (cacheEntry == null) { cacheEntry = new Cache.Entry(); } 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 long now = System.currentTimeMillis(); final long softExpire = now + cacheHitButRefreshed; final long ttl = now + cacheExpired; cacheEntry.data = response.data; cacheEntry.softTtl = softExpire; cacheEntry.ttl = ttl; String headerValue; headerValue = response.headers.get("Date"); if (headerValue != null) { cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue); } headerValue = response.headers.get("Last-Modified"); if (headerValue != null) { cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue); } cacheEntry.responseHeaders = response.headers; return Response.success(response, cacheEntry); } @Override protected void deliverResponse(NetworkResponse response) { mListener.onResponse(response); } @Override protected VolleyError parseNetworkError(VolleyError volleyError) { return super.parseNetworkError(volleyError); } @Override public void deliverError(VolleyError error) { mErrorListener.onErrorResponse(error); } } 

A continuación, en MainActivity, puede llamar así

 CacheRequest cacheRequest = new CacheRequest(0, mUrl, new Response.Listener<NetworkResponse>() { @Override public void onResponse(NetworkResponse response) { try { final String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); JSONObject jsonObject = new JSONObject(jsonString); mTextView.setText(jsonObject.toString(5)); } catch (UnsupportedEncodingException | JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { mTextView.setText(error.toString()); } }); MySingleton.getInstance(this).addToRequestQueue(cacheRequest); 

ACTUALIZACIÓN CON EL CÓDIGO DE FUENTE COMPLETO:

MainActivity.java:

 package com.example.cachevolley; import android.content.Context; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; import com.android.volley.Cache; import com.android.volley.NetworkResponse; import com.android.volley.Request; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.HttpHeaderParser; import com.android.volley.toolbox.Volley; import org.json.JSONException; import org.json.JSONObject; import java.io.UnsupportedEncodingException; public class MainActivity extends AppCompatActivity { private final Context mContext = this; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final TextView textView = (TextView) findViewById(R.id.textView); RequestQueue queue = Volley.newRequestQueue(this); String url = "http://192.168.0.100/apitest"; CacheRequest cacheRequest = new CacheRequest(0, url, new Response.Listener<NetworkResponse>() { @Override public void onResponse(NetworkResponse response) { try { final String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers)); JSONObject jsonObject = new JSONObject(jsonString); textView.setText(jsonObject.toString(5)); Toast.makeText(mContext, "onResponse:\n\n" + jsonObject.toString(), Toast.LENGTH_SHORT).show(); } catch (UnsupportedEncodingException | JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(mContext, "onErrorResponse:\n\n" + error.toString(), Toast.LENGTH_SHORT).show(); } }); // Add the request to the RequestQueue. queue.add(cacheRequest); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } private class CacheRequest extends Request<NetworkResponse> { private final Response.Listener<NetworkResponse> mListener; private final Response.ErrorListener mErrorListener; public CacheRequest(int method, String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) { super(method, url, errorListener); this.mListener = listener; this.mErrorListener = errorListener; } @Override protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) { Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response); if (cacheEntry == null) { cacheEntry = new Cache.Entry(); } 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 long now = System.currentTimeMillis(); final long softExpire = now + cacheHitButRefreshed; final long ttl = now + cacheExpired; cacheEntry.data = response.data; cacheEntry.softTtl = softExpire; cacheEntry.ttl = ttl; String headerValue; headerValue = response.headers.get("Date"); if (headerValue != null) { cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue); } headerValue = response.headers.get("Last-Modified"); if (headerValue != null) { cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue); } cacheEntry.responseHeaders = response.headers; return Response.success(response, cacheEntry); } @Override protected void deliverResponse(NetworkResponse response) { mListener.onResponse(response); } @Override protected VolleyError parseNetworkError(VolleyError volleyError) { return super.parseNetworkError(volleyError); } @Override public void deliverError(VolleyError error) { mErrorListener.onErrorResponse(error); } } } 

Archivo de manifiesto:

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.cachevolley" > <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 

Archivo de diseño:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </RelativeLayout> 

Si la respuesta está tomando del servidor usando la petición de la secuencia entonces apenas substituya la línea

 return Response.success(new JSONObject(jsonString), cacheEntry); 

con este

 return Response.success(new String(jsonString), cacheEntry); 

Funciona en mi caso. Intente con su propio código.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.