-
Notifications
You must be signed in to change notification settings - Fork 305
Recipes (Spanish)
Bienvenido a las recetas de Store!
Existen 3 puntos de entrada en StoreBuilder que pueden ser usados para construir un store. Las diferencias en cuando usar cada uno depende si es que tienes tu propio Key Type y si es que tendras un parser.
public final class StoreBuilder {
...
public static <Parsed> RealStoreBuilder<Parsed, Parsed, BarCode> barcode()
public static <Key, Parsed> RealStoreBuilder<Parsed, Parsed, Key> key()
public static <Key, Raw, Parsed> RealStoreBuilder<Raw, Parsed, Key> parsedWithKey()
...
}
Primero llama get y concatena el resultado con fecth. A continuación, agrega el operador distinct que sólo permitirá emisiones únicas. Si la caché y la red retornan el mismo valor o si la primera llamada get necesita ir a la red, sólo se emitirá 1 elemento.
store.get(barCode)
.concatWith(store.fetch(barCode))
.distinct()
.subscribe()
Nota: Si es que omites distinct()
siempre recibiras dos elementos
store.stream()
.subscribe()
- Nota: Stream continuará obteniendo emisiones para CUALQUIER barcode. Puedes utilizar el operador filter para escuchar un subconjunto de resultados.
A veces deseas obtener nuevos datos cada vez que tu store es limpiado. Un caso de uso común es querer hacer un rerequest de datos a la red cada vez que un usuario envía una solicitud POST diferente. El método publico de store getRefreshing(key) te permite llamar a store.clear(key) en cualquier momento que desees que tu observable se repita(hacer una llamada a la red). Ejemplo de uso:
allNotesStore.getRefreshing(barCode)
.subscribe(observer);
notesApi.submitNewNote(barcode);
allNotesStore.clear(barcode); //cuando clear es llamado, store hara un request a la red de nuevo
Cuando estas usando un Persister es posible que desee volver a llenar su caché de disco en cualquier momento en que el registro es obsoleto. Para ello, agregue un método adicional a su StoreBuilder
e implemente RecordProvider
o utilice nuestro built in RecordPersister
store = StoreBuilder.barcode()
.fetcher(fetcher)
.persister(persister)
.refreshOnStale()
.open();
Store<ArticleAsset, Integer> store = StoreBuilder.<ArticleAsset>barcode()
.fetcher(articleBarcode -> api.getAsset(articleBarcode.getKey(),articleBarcode.getType()))
.persister(new RecordPersister(FileSystemFactory.create(context.getFilesDir()),5, TimeUnit.HOURS))
.open();
Cuando estas usando un Persister es posible que desees actualizar tus datos haciendo un request a internet antes de retornar datos en disco que estan obsoletos. Para ello, agregue un método adicional a su StoreBuilder
e implemente RecordProvider
o utilice nuestro built in RecordPersister
store = StoreBuilder.barcode()
.fetcher(fetcher)
.persister(persister)
.networkBeforeStale()
.open();
Store<ArticleAsset, Integer> store = StoreBuilder.<ArticleAsset>barcode()
.fetcher(articleBarcode -> api.getAsset(articleBarcode.getKey(),articleBarcode.getType()))
.persister(new RecordPersister(FileSystemFactory.create(context.getFilesDir()),5, TimeUnit.HOURS))
.open();
Si desea que store.clear(key) también limpie su caché de disco, haga que su Persister implemente Clearable
Algunas veces usted quiere usar un parser intermediario(middleware) que convierta de json a un pojo y luego use otro parser para desempaquetar tus datos.
Parser<BufferedSource, RedditData> sourceParser = GsonParserFactory.createSourceParser(provideGson(), RedditData.class);
Parser<RedditData, Data> envelopeParser = redditData -> redditData.data();
ParsingStoreBuilder.<BufferedSource,RedditData>builder()
.fetcher(this::fetcher)
.persister(persister)
.parser(new MultiParser<>(Arrays.asList(sourceParser,envelopeParser)))
.open();
En algunos casos necesite convertir un JSONArray que se encuentra en un nivel superior(top level JSONArray), en el cual puedes proveer un TypeToken.
Store<List<Article>> Store = ParsingStoreBuilder.<BufferedSource, List<Article>>builder()
.nonObservableFetcher(this::getResponse)
.parser(GsonParserFactory.createSourceParser(gson, new TypeToken<List<Article>>() {}))
.open();
Por defecto stores almacenarán en caché hasta 100 elementos durante 24 horas utilizando una política expireAfterAccess. Puedes pasar tu propia instancia de Cache
para sobreescribir la duración y tipo de política de almacenamiento en caché. El siguiente ejemplo almacenará 1 elemento para siempre, lo que le permitirá mantener la huella de memoria del store baja.
ParsingStoreBuilder.<BufferedSource,RedditData>builder()
.fetcher(this::fetcher)
.parser(GsonParserFactory.createSourceParser(provideGson(),RedditData.class))
.memory(CacheBuilder.newBuilder()
.maximumSize(1)
.expireAfterWrite(Long.MAX_VALUE, TimeUnit.SECONDS)
.build())
.open();
Hay momentos en los que le gustaría construir un store con algunos métodos auxiliares adicionales. Heredando de store es su mejor apuesta. Con base en lo que pasa en el constructor se denotará cómo se configura el store.
public class SampleStore extends RealStore<String, BarCode> {
@Inject
public SampleStore(Fetcher<String, BarCode> fetcher, Persister<String, BarCode> persister) {
super(fetcher, persister);
}
}
Si desea habilitar el almacenamiento en caché de disco, la forma más sencilla es usar Source Persister agregando compile 'com.nytimes.android:filesystem:VERSION' to your build.gradle
Un source persister puede persistir algo que es un BufferedSource
. Más fácilmente puede obtener un BufferedSource
de Okhttp Response
o Retrofit ResponseBody
. Si utiliza un cliente de red diferente en su fetcher, puede crear un BufferedSource
con:
Okio.buffer(Okio.source(new ByteArrayInputStream(data.getBytes(UTF_8))))
Si viene de un inputStream
Okio.buffer(Okio.source(inputStream))
Una vez que tienes un fetcher
que devuelve un BufferedSource
puedes crear un FileSystemPersister Persister
Persister<BufferedSource, BarCode> persister = FileSystemPersister.create(fileSystem, key ->"Book"+key.getType()+key.getKey())
Cuando utilice FileSystemFactory, debe proporcionar un PathResolver
. El motivo de un PathResolver es permitir el uso compartido del mismo FileSystem
entre varios stores.
StoreBuilder.<BufferedSource>builder()
.fetcher(this::fetcher)
.persister(persister)
.open();
La mayoría de los casos de uso se quiere parsear los datos hacia un pojo en lugar de devolver un BufferedSource
middleware parsers funcionan perfectamente con el SourcePersister
ParsingStoreBuilder.<BufferedSource,RedditData>builder()
.fetcher(this::fetcher)
.persister(persister)
.parser(MoshiParserFactory.createSourceParser(new Moshi.Builder().build(),RedditData.class))
.open();
.parser(JacksonParserFactory.createSourceParser(new ObjectMapper(),RedditData.class))
.parser(GsonParserFactory.createSourceParser(new Gson(),RedditData.class))