Skip to content

Instantly share code, notes, and snippets.

@Marchuck
Created April 29, 2019 07:54
Show Gist options
  • Select an option

  • Save Marchuck/7b1e6573c631c7a61306eb29cbb3c36a to your computer and use it in GitHub Desktop.

Select an option

Save Marchuck/7b1e6573c631c7a61306eb29cbb3c36a to your computer and use it in GitHub Desktop.
//offline-first usecase for api requests
//one you have to do is to include rxjava to your project,
//some Api(could be Retrofit based),
//some Preferences(could SharedPreferences based / some database),
//some SerializerUtil (could be gson, moshi)
import com.google.gson.JsonSyntaxException;
import com.google.gson.annotations.SerializedName;
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;
import java.io.Serializable;
import java.util.concurrent.Callable;
public class CacheEnabledUseCase {
public static final String KEY_CACHED_RESPONSE = "KEY_CACHED_RESPONSE";
private final Api api;
private final Preferences preferences;
private final SerializerUtil<YourResponse> serializerUtil;
class YourResponse implements Serializable {
@SerializedName("field1")
public String field1;
@SerializedName("field2")
public String field2;
}
interface SerializerUtil<T> {
String serialize(T any);
T deserialize(String json, Class<T> klazz) throws JsonSyntaxException;
}
interface Api {
Observable<YourResponse> fetchResponse();
}
interface Preferences {
String getString(String key, String defaultValue);
void putString(String key, String value);
}
public CacheEnabledUseCase(final Api api,
final Preferences preferences,
final SerializerUtil<YourResponse> serializerUtil) {
this.api = api;
this.preferences = preferences;
this.serializerUtil = serializerUtil;
}
public Observable<YourResponse> execute() {
final YourResponse cachedResponse = getCachedResponseOrNull();
if (cachedResponse != null) {
return executeCached(cachedResponse)
.concatWith(
executeFreshAndPersist().onErrorResumeNext(Observable.<YourResponse>empty())//if fresh failed, only cached will be emitted
);
} else {
return executeFreshAndPersist();
}
}
private Observable<YourResponse> executeCached(final YourResponse cachedResponse) {
return Observable.fromCallable(new Callable<YourResponse>() {
@Override
public YourResponse call() {
return cachedResponse;
}
});
}
private Observable<YourResponse> executeFreshAndPersist() {
return api.fetchResponse()
.doAfterNext(new Consumer<YourResponse>() {
@Override
public void accept(YourResponse yourResponse) {
putToCache(yourResponse);
}
});
}
private void putToCache(YourResponse successfullResponse) {
String res = serializerUtil.serialize(successfullResponse);
preferences.putString(KEY_CACHED_RESPONSE, res);
}
private YourResponse getCachedResponseOrNull() {
String json = preferences.getString(KEY_CACHED_RESPONSE, null);
if (json != null) {
try {
return serializerUtil.deserialize(json, YourResponse.class);
} catch (JsonSyntaxException x) {
//empty catch block. if it is failed, no cache is supported
}
}
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment