package com.zcy.ghost.vivideo.model.net;
import com.zcy.ghost.vivideo.BuildConfig;
import com.zcy.ghost.vivideo.app.Constants;
import com.zcy.ghost.vivideo.model.bean.VideoRes;
import com.zcy.ghost.vivideo.model.exception.ExceptionEngine;
import com.zcy.ghost.vivideo.model.exception.ServerException;
import com.zcy.ghost.vivideo.utils.KL;
import com.zcy.ghost.vivideo.utils.SystemUtils;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.Cache;
import okhttp3.CacheControl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
public class HttpMethods {
public static final String BASE_HOST_URL = VideoApis.HOST;
private Retrofit retrofit;
private VideoApis mService;
private static OkHttpClient okHttpClient;
private static void initOkHttp() {
if (okHttpClient == null) {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BASIC);
builder.addInterceptor(loggingInterceptor);
}
File cacheFile = new File(Constants.PATH_CACHE);
Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);
Interceptor cacheInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!SystemUtils.isNetworkConnected()) {
request = request.newBuilder()
.cacheControl(CacheControl.FORCE_CACHE)
.build();
}
int tryCount = 0;
Response response = chain.proceed(request);
while (!response.isSuccessful() && tryCount < 3) {
KL.d(RetrofitHelper.class, "interceptRequest is not successful - :{}", tryCount);
tryCount++;
// retry the request
response = chain.proceed(request);
}
if (SystemUtils.isNetworkConnected()) {
int maxAge = 0;
// 有网络时, 不缓存, 最大保存时长为0
response.newBuilder()
.header("Cache-Control", "public, max-age=" + maxAge)
.removeHeader("Pragma")
.build();
} else {
// 无网络时,设置超时为4周
int maxStale = 60 * 60 * 24 * 28;
response.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.removeHeader("Pragma")
.build();
}
return response;
}
};
//设置缓存
builder.addNetworkInterceptor(cacheInterceptor);
builder.addInterceptor(cacheInterceptor);
builder.cache(cache);
//设置超时
builder.connectTimeout(10, TimeUnit.SECONDS);
builder.readTimeout(20, TimeUnit.SECONDS);
builder.writeTimeout(20, TimeUnit.SECONDS);
//错误重连
builder.retryOnConnectionFailure(true);
okHttpClient = builder.build();
}
}
//构造方法私有
private HttpMethods() {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_HOST_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
mService = retrofit.create(VideoApis.class);
}
//在访问HttpMethods时创建单例
private static class SingletonHolder {
private static final HttpMethods INSTANCE = new HttpMethods();
}
//获取单例
public static HttpMethods getInstance() {
initOkHttp();
return SingletonHolder.INSTANCE;
}
/**
* ClassificationPresenter
*
* @return
*/
public Observable<VideoRes> queryClassification() {
return mService.getHomePage()
.map(new ServerResultFunc<VideoRes>())
.onErrorResumeNext(new HttpResultFunc<VideoRes>())
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
private class ServerResultFunc<T> implements Func1<VideoHttpResponse<T>, T> {
@Override
public T call(VideoHttpResponse<T> httpResult) {
if (httpResult.getCode() != 200) {
throw new ServerException(httpResult.getCode(), httpResult.getMsg());
}
return httpResult.getRet();
}
}
private class HttpResultFunc<T> implements Func1<Throwable, Observable<T>> {
@Override
public Observable<T> call(Throwable throwable) {
return Observable.error(ExceptionEngine.handleException(throwable));
}
}
}