基于RxJava+Retrofit封装的网络框架

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) {
        mSwitchViewHelper.showLoading();
    }
    @Override
    protected void onResponse(BaseResult<T> result, Status status) {
        switch (status) {
            case SUCCESS:
                mSwitchViewHelper.showContent();
                onSuccess(result.getResult());
                break;
            case NOT_DATA:
                mSwitchViewHelper.showEmpty();
                break;
            case NOT_LOGIN:
                mSwitchViewHelper.showLogin(t.getMessage());
                break;
            case FAILURE:
                mSwitchViewHelper.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 showLogin();
    void showError();
}

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展现给用户,仅此而已,做个记录

猜你喜欢

转载自blog.csdn.net/zhangbo328/article/details/80832901
今日推荐