1.依赖库引入
implementation 'io.reactivex.rxjava2:rxjava:2.1.7'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
2.基类设计
/**
* 创建一个中间类用于建立M层和V层之间的连接,其实就是统一一个调用的入口,方便维护扩展
*/
public class Present<T extends BaseResult>{
protected BaseObserver mObserver;
public Present(BaseObserver observer) {
mObserver = observer;
//可根据mObserver的扩展属性进行相应的初始化管理
}
public void execute(Observable<T> observable) {
if (mObserver.isLoading()) return;
observable
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
//RxJava中map操作符也可以实现BaseObserver中对于接口规范中基础数据的处理,自行选择
/**.map(new Function<BaseResult<T>, T>() {
@Override
public T apply(BaseResult<T> base){
return base.getResult();
}
})**/
.subscribe(mObserver);
}
public static void execute(Observable observable, BaseObserver observer) {
observable
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
}
}
/**
* 基础的观察者,类似传统BaseCallBack,处理接口规范的基层响应,该类应保持最基本的功能
* 继承该类可扩展为与View层交互刷新页面,上传,列表刷新之类的Observer(ViewObserver)
*/
public abstract class BaseObserver<T extends BaseResult> implements Observer<T> {
public enum Status {
SUCCESS, NOT_DATA, FAILURE, NOT_LOGIN,
}
protected Disposable mDisposable;
protected boolean isLoading;
@Override
public void onSubscribe(@NonNull Disposable d) {//类似onBefore(),可初始化菊花圈之类...
Logger.i("onBefore");
mDisposable = d;
}
@Override
public void onNext(@NonNull T t) { //基础响应的处理,可根据后端业务调整,不与View耦合
if(t==null){
onError(new Throwable("系统异常"));
return;
}
if(t.getCode()==0){
onResponse(t,SUCCESS);
}else if(t.getCode()==999){
onResponse(t,NOT_LOGIN);
}else{
onResponse(t,FAILURE);
}
}
protected abstract void onResponse(@NonNull T t, Status status);
@Override
public void onError(@NonNull Throwable e) {
isLoading = false;
}
@Override
public void onComplete() {
isLoading = false;
}
public boolean isLoading() {
return isLoading;
}
}
/**
* 基于与View层交互的Observer,将页面切换的操作统一封装在IViewSwitchImp类中
* IViewSwitchImp代码可自行封装实现,此处只给出IViewSwitch 接口定义
*/
public abstract class ViewObserver<T> extends BaseObserver<BaseResult<T>> {
protected IViewSwitch mIView;
public ViewObserver(ViewGroup container) {
mIView = new IViewSwitchImp(contentView);
}
public ViewObserver(IViewSwitch view) {
mIView= view;
}
@Override
public void onSubscribe(@NonNull Disposable d) {
mIView.showLoading();
}
@Override
protected void onResponse(BaseResult<T> result, Status status) {
switch (status) {
case SUCCESS:
mIView.showContent();
onSuccess(result.getResult());
break;
case NOT_DATA:
mIView.showEmpty();
break;
case NOT_LOGIN:
mIView.showLogin(t.getMessage());
break;
case FAILURE:
mIView.showError(result.getMessage());
break;
}
}
public abstract void onSuccess(T t);
@Override
public void onError(@NonNull Throwable e) {
Logger.d(e.getMessage());
if (hasLoadDataSuccess) {
Toaster.show(e.getMessage());
} else {
mSwitchViewHelper.showFailure(e);
}
}
}
public interface IViewSwitch{
void showContent();
void showEmpty();
void showLoading();
void showError(String msg);
}
3.Retrofit的封装
public class RetrofitFactory {
private static final java.lang.Object Object = new Object();
/**
* 缓存机制
* 在响应请求之后在 data/data/<包名>/cache 下建立一个response 文件夹,保持缓存数据。
* 这样我们就可以在请求的时候,如果判断到没有网络,自动读取缓存的数据。
* 同样这也可以实现,在我们没有网络的情况下,重新打开App可以浏览的之前显示过的内容。
* 也就是:判断网络,有网络,则从网络获取,并保存到缓存中,无网络,则从缓存中获取。
* https://werb.github.io/2016/07/29/%E4%BD%BF%E7%94%A8Retrofit2+OkHttp3%E5%AE%9E%E7%8E%B0%E7%BC%93%E5%AD%98%E5%A4%84%E7%90%86/
*/
private static final Interceptor cacheControlInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (!NetWorkUtil.isNetworkConnected(MyApplication.AppContext)) {
request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
}
Response originalResponse = chain.proceed(request);
if (NetWorkUtil.isNetworkConnected(MyApplication.AppContext)) {
// 有网络时 设置缓存为默认值
String cacheControl = request.cacheControl().toString();
return originalResponse.newBuilder()
.header("Cache-Control", cacheControl)
.removeHeader("Pragma")
.build();
} else {
// 无网络时 设置超时为1周
int maxStale = 60 * 60 * 24 * 7;
return originalResponse.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.removeHeader("Pragma")
.build();
}
}
};
private volatile static Retrofit retrofit;
@NonNull
public static Retrofit getRetrofit() {
synchronized (Object) {
if (retrofit == null) {
// 指定缓存路径,缓存大小 50Mb
Cache cache = new Cache(new File(MyApplication.AppContext.getCacheDir(), "HttpCache"),
1024 * 1024 * 50);
// // Cookie 持久化
// ClearableCookieJar cookieJar =
// new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(InitApp.AppContext));
OkHttpClient.Builder builder = new OkHttpClient.Builder()
// .cookieJar(cookieJar)
.cache(cache)
.addInterceptor(cacheControlInterceptor)
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.retryOnConnectionFailure(true);
// Log 拦截器
if (BuildConfig.DEBUG) {
builder = HttpBuilderWrapper.initInterceptor(builder);
}
retrofit = new Retrofit.Builder()
.baseUrl(ApiConstant.HOST)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
return retrofit;
}
}
}
public interface IHomeApi {
@FormUrlEncoded
@POST("/goods/guessyoulikes/v2")
Observable<BaseResult<HomeBean>> getContentList( @Field("userId")int userId);
}
4.调用
Observable<BaseResult<HomeBean>> observable = RetrofitFactory.getRetrofit().create(IHomeApi.class).getContentList(9527);
Present present = new Present(new ViewObserver<HomeBean>(new IViewSwitch()){
@Override
public void onSuccess(HomeBean bean){
}
});
present.excute(observable);
Emmm… 写完发现并没有什么卵用,用Rxjava自带的链式调用似乎更简洁,这样做的好处在于,将网络的异常响应统一封装在一个可扩展的BaseObserver中并通过IViewSwitch展现给用户,仅此而已,做个记录