2012-10-05 85 views
14

Mi aplicación para Android obtiene sus datos mediante la API REST. Quiero tener implementado el caché del lado del cliente. ¿Tenemos alguna clase incorporada para esto?¿Cómo implementar el almacenamiento en caché en la aplicación de Android para REST API resultados?

si no es así, ¿hay algún código que pueda volver a utilizar? Recuerdo haberme encontrado con ese código alguna vez. Sin embargo, no puedo encontrarlo.

Si nada funciona, escribiré el mío. Lo que sigue es la estructura básica

public class MyCacheManager { 

static Map<String, Object> mycache; 

public static Object getData(String cacheid) { 
    return mycache.get(cacheid); 
} 

public static void putData(String cacheid, Object obj, int time) { 
    mycache.put(cacheid, obj); 
} 

} 

¿Cómo activo el tiempo de objetos almacenados en caché? también, ¿cuál es la mejor manera de serializar? la memoria caché debe estar intacta incluso si la aplicación está cerrada y se vuelve a abrir más tarde (si el tiempo no ha expirado).

Gracias Ajay

Respuesta

3

Una de las mejores maneras es utilizar Matthias Käppler de librarys encendió para hacer peticiones HTTP que almacena en caché las respuestas en la memoria (referencia débil) y en el archivo. Es realmente configurable para hacer uno u otro o ambos.

La biblioteca se encuentra aquí: https://github.com/mttkay/ignition con ejemplos que se encuentran aquí: https://github.com/mttkay/ignition/wiki/Sample-applications

Personalmente, me encanta este lib desde cuando se llamaba Droidfu

la esperanza que esto le ayuda tanto como lo hizo conmigo Ajay!

9

Ahora impresionante voleo biblioteca publicado el Google I/O 2013 que ayuda a mejorar sobre todos los problemas de llamar a la API REST:

Volley is a library, es biblioteca llamada voleo desde el equipo de desarrollo de Android. eso hace que las redes para las aplicaciones de Android sean más fáciles y, lo que es más importante, más rápidas. Gestiona el procesamiento y el almacenamiento en memoria caché de las solicitudes de red y ahorra a los desarrolladores un valioso tiempo al escribir el mismo código de llamada/caché de red una y otra vez. Y una ventaja más de tener menos código es una menor cantidad de errores y eso es lo que todos los desarrolladores quieren y busca.

Ejemplo para volea: technotalkative

+0

Gran! También puede encontrar algunas buenas muestras del uso de Volley aquí: https://github.com/stormzhang/AndroidVolley – Sam003

0

primer cheque el dispositivo está conectado a través de Internet o no.

public class Reachability { 

private final ConnectivityManager mConnectivityManager; 


public Reachability(Context context) { 
    mConnectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); 
} 

public boolean isConnected() { 
    NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo(); 
    return networkInfo != null && networkInfo.isConnectedOrConnecting(); 
}} 

Si el dispositivo está conectado a Internet a continuación, obtener los datos de la API y la memoria caché en otro obtener los datos de la memoria caché.

public class CacheManager { 

Cache<String, String> mCache; 
private DiskLruCache mDiskLruCache; 
private final Context mContext; 

public CacheManager(Context context) throws IOException { 
    mContext = context; 
    setUp(); 
    mCache = DiskCache.getInstanceUsingDoubleLocking(mDiskLruCache); 
} 

public void setUp() throws IOException { 
    File cacheInFiles = mContext.getFilesDir(); 
    int version = BuildConfig.VERSION_CODE; 

    int KB = 1024; 
    int MB = 1024 * KB; 
    int cacheSize = 400 * MB; 

    mDiskLruCache = DiskLruCache.open(cacheInFiles, version, 1, cacheSize); 
} 

public Cache<String, String> getCache() { 
    return mCache; 
} 

public static class DiskCache implements Cache<String, String> { 

    private static DiskLruCache mDiskLruCache; 
    private static DiskCache instance = null; 

    public static DiskCache getInstanceUsingDoubleLocking(DiskLruCache diskLruCache){ 
     mDiskLruCache = diskLruCache; 
     if(instance == null){ 
      synchronized (DiskCache.class) { 
       if(instance == null){ 
        instance = new DiskCache(); 
       } 
      } 
     } 
     return instance; 
    } 

    @Override 
    public synchronized void put(String key, String value) { 
     try { 
      if (mDiskLruCache != null) { 
       DiskLruCache.Editor edit = mDiskLruCache.edit(getMd5Hash(key)); 
       if (edit != null) { 
        edit.set(0, value); 
        edit.commit(); 
       } 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public synchronized String get(String key) { 
     try { 
      if (mDiskLruCache != null) { 
       DiskLruCache.Snapshot snapshot = mDiskLruCache.get(getMd5Hash(key)); 

       if (snapshot == null) { 
        // if there is a cache miss simply return null; 
        return null; 
       } 

       return snapshot.getString(0); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     // in case of error in reading return null; 
     return null; 
    } 

    @Override 
    public String remove(String key) { 
     // TODO: implement 
     return null; 
    } 

    @Override 
    public void clear() { 
     // TODO: implement 
    } 
} 

public static String getMd5Hash(String input) { 
    try { 
     MessageDigest md = MessageDigest.getInstance("MD5"); 
     byte[] messageDigest = md.digest(input.getBytes()); 
     BigInteger number = new BigInteger(1, messageDigest); 
     String md5 = number.toString(16); 

     while (md5.length() < 32) 
      md5 = "0" + md5; 

     return md5; 
    } catch (NoSuchAlgorithmException e) { 
     Log.e("MD5", e.getLocalizedMessage()); 
     return null; 
    } 
}} 

crear la clase CacheInterceptor para almacenar en caché la respuesta de la red y controlar los errores

public class CacheInterceptor implements Interceptor{ 
private final CacheManager mCacheManager; 
private final Reachability mReachability; 

public CacheInterceptor(CacheManager cacheManager, Reachability reachability) { 
    mCacheManager = cacheManager; 
    mReachability = reachability; 
} 

@Override 
public Response intercept(Chain chain) throws IOException { 
    Request request = chain.request(); 
    String key = request.url().toString(); 

    Response response; 
    if (mReachability.isConnected()) { 
     try { 
      response = chain.proceed(request); 
      Response newResponse = response.newBuilder().build(); 

      if (response.isSuccessful()) { 
       if (response.code() == 204) { 
        return response; 
       } 
       // save to cache this success model. 
       mCacheManager.getCache().put(key, newResponse.body().string()); 

       // now we know that we definitely have a cache hit. 
       return getCachedResponse(key, request); 
      }else if (response.code() >= 500) { // accommodate all server errors 

       // check if there is a cache hit or miss. 
       if (isCacheHit(key)) { 
        // if data is in cache, the return the data from cache. 
        return getCachedResponse(key, request); 
       }else { 
        // if it's a miss, we can't do much but return the server state. 
        return response; 
       } 

      }else { // if there is any client side error 
       // forward the response as it is to the business layers to handle. 
       return response; 
      } 
     } catch (ConnectException | UnknownHostException e) { 
      // Internet connection exception. 
      e.printStackTrace(); 
     } 
    } 

    // if somehow there is an internet connection error 
    // check if the data is already cached. 
    if (isCacheHit(key)) { 
     return getCachedResponse(key, request); 
    }else { 
     // if the data is not in the cache we'll throw an internet connection error. 
     throw new UnknownHostException(); 
    } 
} 

private Response getCachedResponse(String url, Request request) { 
    String cachedData = mCacheManager.getCache().get(url); 

    return new Response.Builder().code(200) 
      .body(ResponseBody.create(MediaType.parse("application/json"), cachedData)) 
      .request(request) 
      .protocol(Protocol.HTTP_1_1) 
      .build(); 
} 

public boolean isCacheHit(String key) { 
    return mCacheManager.getCache().get(key) != null; 
}} 

Ahora agregue el interceptor en este OkHttpClient al crear el servicio a través de reequipamiento.

public final class ServiceManager { 
private static ServiceManager mServiceManager; 

public static ServiceManager get() { 
    if (mServiceManager == null) { 
     mServiceManager = new ServiceManager(); 
    } 
    return mServiceManager; 
} 

public <T> T createService(Class<T> clazz, CacheManager cacheManager, Reachability reachability) { 
    return createService(clazz, HttpUrl.parse(ServiceApiEndpoint.SERVICE_ENDPOINT), cacheManager, reachability); 
} 

private <T> T createService(Class<T> clazz, HttpUrl parse, CacheManager cacheManager, Reachability reachability) { 
    Retrofit retrofit = getRetrofit(parse, cacheManager, reachability); 
    return retrofit.create(clazz); 
} 

public <T> T createService(Class<T> clazz) { 
    return createService(clazz, HttpUrl.parse(ServiceApiEndpoint.SERVICE_ENDPOINT)); 
} 

private <T> T createService(Class<T> clazz, HttpUrl parse) { 
    Retrofit retrofit = getRetrofit(parse); 
    return retrofit.create(clazz); 
} 

private <T> T createService(Class<T> clazz, Retrofit retrofit) { 
    return retrofit.create(clazz); 
} 

private Retrofit getRetrofit(HttpUrl httpUrl, CacheManager cacheManager, Reachability reachability) { 
    return new Retrofit.Builder() 
      .baseUrl(httpUrl) 
      .client(createClient(cacheManager, reachability)) 
      .addConverterFactory(getConverterFactory()) 
      .build(); 
} 

private OkHttpClient createClient(CacheManager cacheManager, Reachability reachability) { 
    return new OkHttpClient.Builder().addInterceptor(new CacheInterceptor(cacheManager, reachability)).build(); 
} 

private Retrofit getRetrofit(HttpUrl parse) { 
    return new Retrofit.Builder() 
      .baseUrl(parse) 
      .client(createClient()) 
      .addConverterFactory(getConverterFactory()).build(); 
} 

private Retrofit getPlainRetrofit(HttpUrl httpUrl) { 
    return new Retrofit.Builder() 
      .baseUrl(httpUrl) 
      .client(new OkHttpClient.Builder().build()) 
      .addConverterFactory(getConverterFactory()) 
      .build(); 
} 

private Converter.Factory getConverterFactory() { 
    return GsonConverterFactory.create(); 
} 

private OkHttpClient createClient() { 
    return new OkHttpClient.Builder().build(); 
}} 

interfaz de caché

public interface Cache<K, V> { 

void put(K key, V value); 

V get(K key); 

V remove(K key); 

void clear();} 
Cuestiones relacionadas