package com.xiecc.seeWeather.component;
import com.facebook.stetho.okhttp3.StethoInterceptor;
import com.litesuits.orm.db.assit.WhereBuilder;
import com.xiecc.seeWeather.BuildConfig;
import com.xiecc.seeWeather.base.BaseApplication;
import com.xiecc.seeWeather.common.C;
import com.xiecc.seeWeather.common.utils.RxUtil;
import com.xiecc.seeWeather.common.utils.ToastUtil;
import com.xiecc.seeWeather.common.utils.Util;
import com.xiecc.seeWeather.modules.about.domain.Version;
import com.xiecc.seeWeather.modules.main.domain.CityORM;
import com.xiecc.seeWeather.modules.main.domain.Weather;
import io.reactivex.Observable;
import io.reactivex.functions.Consumer;
import java.io.File;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by zk on 2015/12/16.
* update by hugo thanks for brucezz
*/
public class RetrofitSingleton {
private static ApiInterface sApiService = null;
private static Retrofit sRetrofit = null;
private static OkHttpClient sOkHttpClient = null;
private void init() {
initOkHttp();
initRetrofit();
sApiService = sRetrofit.create(ApiInterface.class);
}
private RetrofitSingleton() {
init();
}
public static RetrofitSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
private static class SingletonHolder {
private static final RetrofitSingleton INSTANCE = new RetrofitSingleton();
}
private static void initOkHttp() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
// 缓存 http://www.jianshu.com/p/93153b34310e
File cacheFile = new File(C.NET_CACHE);
Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
Interceptor cacheInterceptor = chain -> {
Request request = chain.request();
if (!Util.isNetworkConnected(BaseApplication.getAppContext())) {
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
Response response = chain.proceed(request);
Response.Builder newBuilder = response.newBuilder();
if (Util.isNetworkConnected(BaseApplication.getAppContext())) {
int maxAge = 0;
// 有网络时 设置缓存超时时间0个小时
newBuilder.header("Cache-Control", "public, max-age=" + maxAge);
} else {
// 无网络时,设置超时为4周
int maxStale = 60 * 60 * 24 * 28;
newBuilder.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale);
}
return newBuilder.build();
};
builder.cache(cache).addInterceptor(cacheInterceptor);
if (BuildConfig.DEBUG) {
builder.addNetworkInterceptor(new StethoInterceptor());
}
//设置超时
builder.connectTimeout(15, TimeUnit.SECONDS);
builder.readTimeout(20, TimeUnit.SECONDS);
builder.writeTimeout(20, TimeUnit.SECONDS);
//错误重连
builder.retryOnConnectionFailure(true);
sOkHttpClient = builder.build();
}
private static void initRetrofit() {
sRetrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.HOST)
.client(sOkHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
private static Consumer<Throwable> disposeFailureInfo(Throwable t) {
return throwable -> {
if (t.toString().contains("GaiException") || t.toString().contains("SocketTimeoutException") ||
t.toString().contains("UnknownHostException")) {
ToastUtil.showShort("网络问题");
} else if (t.toString().contains("API没有")) {
OrmLite.getInstance()
.delete(new WhereBuilder(CityORM.class).where("name=?", Util.replaceInfo(t.getMessage())));
ToastUtil.showShort("错误: " + t.getMessage());
}
PLog.w(t.getMessage());
};
}
public Observable<Weather> fetchWeather(String city) {
return sApiService.mWeatherAPI(city, C.KEY)
.flatMap(weather -> {
String status = weather.mWeathers.get(0).status;
if ("no more requests".equals(status)) {
return Observable.error(new RuntimeException("/(ㄒoㄒ)/~~,API免费次数已用完"));
} else if ("unknown city".equals(status)) {
return Observable.error(new RuntimeException(String.format("API没有%s", city)));
}
return Observable.just(weather);
})
.map(weather -> weather.mWeathers.get(0))
.doOnError(RetrofitSingleton::disposeFailureInfo)
.compose(RxUtil.io());
}
public Observable<Version> fetchVersion() {
return sApiService.mVersionAPI(C.API_TOKEN)
.compose(RxUtil.io());
}
}