I'm using Retrofit 2.0 and Robospice libraries, included in gradle file like this:
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
compile 'com.octo.android.robospice:robospice-retrofit:1.4.14'
I want to use the RetrofitGsonSpiceService
but when I run the application I get a Suppressed: java.lang.ClassNotFoundException: retrofit.converter.GsonConverter
It's caused by the
@Override
protected Converter createConverter() {
return new GsonConverter(new Gson());
}
method of the RetrofitGsonSpiceService
class.
In Retrofit 2.0 the default Converter is now excluded.
My question is do you know a simple way of configuring Robospice to easily work with Retrofit 2.0, or is out there a preconfigured SpiceService to work with the new Retrofit 2.0?
Not so simple as before...
PS. I used Moshi parser, but with GSON it should be similar.
You should extend SpiceService
:
public class SpiceNetworkService extends SpiceService {
private Map<Class<?>, Object> retrofitInterfaceToServiceMap = new HashMap<>();
protected List<Class<?>> retrofitInterfaceList = new ArrayList<>();
@Override
public void onCreate() {
super.onCreate();
addRetrofitInterface(WallpapersApi.class);
}
@SuppressWarnings("unchecked")
protected <T> T getRetrofitService(Class<T> serviceClass) {
T service = (T) retrofitInterfaceToServiceMap.get(serviceClass);
if (service == null) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(getServerUrl())
.addConverterFactory(MoshiConverterFactory.create())
.build();
service = retrofit.create(serviceClass);
retrofitInterfaceToServiceMap.put(serviceClass, service);
}
return service;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
public void addRequest(CachedSpiceRequest<?> request, Set<RequestListener<?>> listRequestListener) {
if (request.getSpiceRequest() instanceof RetrofitSpiceRequest) {
RetrofitSpiceRequest retrofitSpiceRequest = (RetrofitSpiceRequest) request.getSpiceRequest();
retrofitSpiceRequest.setService(getRetrofitService(retrofitSpiceRequest.getRetrofitedInterfaceClass()));
}
super.addRequest(request, listRequestListener);
}
public final List<Class<?>> getRetrofitInterfaceList() {
return retrofitInterfaceList;
}
protected void addRetrofitInterface(Class<?> serviceClass) {
retrofitInterfaceList.add(serviceClass);
}
@Override
public CacheManager createCacheManager(Application application) throws CacheCreationException {
CacheManager cacheManager = new CacheManager();
cacheManager.addPersister(new MoshiPersisterFactory(application, getCacheFolder()));
return cacheManager;
}
protected String getServerUrl() {
return SpiceWallpapersRequest.API_URL;
}
public File getCacheFolder() {
return null;
}
}
Implement Persister factory like this:
public class MoshiPersisterFactory extends InFileObjectPersisterFactory {
public MoshiPersisterFactory(Application application) throws CacheCreationException {
super(application);
}
public MoshiPersisterFactory(Application application, File cacheFolder) throws CacheCreationException {
super(application, cacheFolder);
}
public MoshiPersisterFactory(Application application, List<Class<?>> listHandledClasses) throws CacheCreationException {
super(application, listHandledClasses);
}
public MoshiPersisterFactory(Application application, List<Class<?>> listHandledClasses, File cacheFolder) throws CacheCreationException {
super(application, listHandledClasses, cacheFolder);
}
@Override
public <T> InFileObjectPersister<T> createInFileObjectPersister(Class<T> clazz, File cacheFolder) throws CacheCreationException {
return new MoshiPersister<>(getApplication(), clazz, cacheFolder);
}
}
Finally extend InFileObjectPersister:
public class MoshiPersister extends InFileObjectPersister { public MoshiPersister(Application application, Class clazz) throws CacheCreationException { super(application, clazz); }
public MoshiPersister(Application application, Class<T> clazz, File cacheFolder) throws CacheCreationException {
super(application, clazz, cacheFolder);
}
@Override
protected T readCacheDataFromFile(File file) throws CacheLoadingException {
BufferedSource sink = null;
try {
InputStream fileInputStream = new FileInputStream(file);
sink = Okio.buffer(Okio.source(fileInputStream));
Moshi moshi = new Moshi.Builder().build();
JsonAdapter<T> jsonAdapter = moshi.adapter(getHandledClass());
return jsonAdapter.fromJson(sink);
} catch (FileNotFoundException e) {
// Should not occur (we test before if file exists)
// Do not throw, file is not cached
Ln.w("file " + file.getAbsolutePath() + " does not exists", e);
return null;
} catch (Exception e) {
throw new CacheLoadingException(e);
} finally {
try {
if (sink != null) {
sink.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public T saveDataToCacheAndReturnData(final T data, final Object cacheKey) throws CacheSavingException {
try {
if (isAsyncSaveEnabled()) {
Thread t = new Thread() {
@Override
public void run() {
try {
saveData(data, cacheKey);
} catch (IOException | CacheSavingException e) {
Ln.w("An error occured on saving request " + cacheKey + " data asynchronously");
}
}
};
t.start();
} else {
saveData(data, cacheKey);
}
} catch (CacheSavingException e) {
throw e;
} catch (Exception e) {
throw new CacheSavingException(e);
}
return data;
}
private void saveData(T data, Object cacheKey) throws IOException, CacheSavingException {
Moshi moshi = new Moshi.Builder().build();
JsonAdapter<T> jsonAdapter = moshi.adapter(getHandledClass());
BufferedSink sink = new Buffer();
jsonAdapter.toJson(sink, data);
FileOutputStream out = null;
try {
out = new FileOutputStream(getCacheFile(cacheKey));
sink.buffer().copyTo(out);
} finally {
if (out != null) {
out.close();
}
}
}
}