Android 我的Retrofit+Rxjava封装,不搞花里

作者: Jlanglang | 来源:发表于2019-10-07 09:47 被阅读0次

    前言

    从我最开始用rx和retrofit.到现在,快3年了.

    这个库的内容,算是沉淀下来的东西.

    个人用这个做过的项目也有很多个了.和项目中用的有点区别.

    因为不能随便重构的原因,比项目里的更好.哈哈.

    目录:

    image

    初始化:

    NetWorkManager.init(String baseUrl, Application context)
    

    难点1 BaseBean:

    作为一个库,这个类是一个头疼的问题.因为强耦合.

    我们一般写的baseBaen都是这样的:

    class BaseBean<T>{
      String code;
      T data;
      String msg;
    }
    

    不同的人,有不同的协议,字段名会不一样,如果用这样的,明显是不行的.

    这个库是这样的(ParseInfo):

    你只需要定义自己的basebean规则,即可

    image

    例子

     NetWorkManager.addParseInfo(
                    new RxParseInfo("code", "data", "msg", "200") //200代表成功时的code.
            );
    
    

    这里传入的参数都是key的名字.

    目前支持3个key值.我觉得基本够用了.

    codeKey判断成功

    dataKey返回数据

    msgKey服务器返回消息

    库是如何判断接口请求成功的

    ParseInfo 里默认通过判断successCode与返回的codeKey的值进行比较的

     public boolean isSuccess(JsonObject asJsonObject) {
            if (checkSuccess != null) {
                return checkSuccess.isSuccess(asJsonObject);
            }
            String code = asJsonObject.get(codeKey).toString();
            return TextUtils.equals(code, successCode);
        }
    

    也可以自定义判断是否请求成功

    ParseInfo使用setCheckSuccess().非必须.主要是为了扩展.

    new ParseInfo("code", "data", "msg", "200")
     .setCheckSuccess(new ParseInfo.CheckSuccess() {
                        @Override
                        public boolean isSuccess(JsonObject asJsonObject) {
                            return false;
                        }
                    })
    

    请求:

    public interface JApi {
    
        /**
         * 上传文件
          */
        @POST
        @Multipart
        Observable<String> post(@Url String url, @PartMap HashMap<String, RequestBody> params);
    
        /**
         * 通用POST
         *
         */
        @POST
        Observable<String> post(@Url String url, @Body String json);
    
        /**
         * 通用POST
         */
        @POST
        Observable<String> post(@Url String url, @Body SimpleParams json);
    
        /**
         * 通用get
         */
        @GET
        Observable<String> get(@Url String url, @QueryMap SimpleParams params);
    
    }
    

    这里写了4个通用的retrofit的请求.我个人觉得是可以满足大部分的需求了.

    如果满足不了.就写点定制的就好了.有人会觉得这么写不行,实际上,我就用这个已经写了很多项目了.

    有人会问,为什么这里都是Observable<String>,往后面看就知道了.嘿嘿

    RetrofitUtil

    这里使用了饿汉式懒加载单例.

    public class RetrofitUtil {
        /**
         * 服务器地址
         */
        private static String API_HOST;
        private static Application mContext;
        private static final HashMap<Class, Object> apis = new HashMap<>();
    
        @SuppressWarnings("unchecked")
        public static <T> T getApi(Class<T> c) {
            Object o = apis.get(c);
            if (null == o) {
                o = getInstance().create(c);
                apis.put(c, o);
            }
            return (T) o;
        }
    
        public static synchronized void init(String baseUrl, Application context) {
            if (TextUtils.isEmpty(baseUrl)) {
                return;
            }
            mContext = context;
            API_HOST = baseUrl;
            Instance.retrofit = Instance.getRetrofit();
            apis.clear();
        }
    
        public static Retrofit getInstance() {
            return Instance.retrofit;
        }
    
        private static class Instance {
            private static Retrofit retrofit = getRetrofit();
    
            private static Retrofit getRetrofit() {
                OkHttpClient.Builder client = new OkHttpClient.Builder()
                        //拦截并设置缓存
                        .addNetworkInterceptor(new CacheInterceptor())
                        //拦截并设置缓存
                        .addInterceptor(new CacheInterceptor())
                        .cache(new Cache(mContext.getCacheDir(), 10240 * 1024));
                // 设置代理
                if (NetWorkManager.getProxy() != null) {
                    client.proxy(NetWorkManager.getProxy());
                }
    
                for (Interceptor i : NetWorkManager.mInterceptors) {
                    client.addInterceptor(i);
                }
                if (BuildConfig.DEBUG) {
                    HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
                    interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
                    client.addInterceptor(interceptor);
                }
                return new Retrofit.Builder()
                        .client(client.build())
                        .baseUrl(API_HOST)
                        .addConverterFactory(GsonConverterFactory.create())
                        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                        .build();
            }
        }
    
    

    可以设置缓存,添加代理,重置baseurl

    对Retrofit.create创建的实体类,进行了缓存.

    看了半天,先来个例子吧:

    Disposable login = RetrofitUtil.getApi(JApi.class)
                    .get("/login", SimpleParams.create()
                            .putP("key1", 1)
                            .putP("key2", 2)
                            .putP("key3", 2)
                            .putP("key4", 3)
                    )
                    .compose(JRxCompose.normal())
                    .subscribe(new Consumer<String>() {
                        @Override
                        public void accept(String s) throws Exception {
    
                        }
                    });
    

    一个简单的请求就是这样的.

    有人看了会问, JRxCompose是啥?

    JRxCompose

    先来张目录图

    image

    再来张代码

    image

    这里为什么要写JsonArrayParesTransformerJsonParesTransformer.

    因为在组件化的时候,跨组件GSON解析时,泛型是会丢失的.我不知道现在解决没.

    所以使用这两个来统一解析结果.

    如果你细心就会发现.JApi的方法,的返回参数都是Observable<String>

    也就是统一先用String接收结果,然后再解析成最终结果.


    看到这里,你满足了吗? 我是不满足的.哈哈

    难点2 取消网络请求

    如何舒服的取消请求回调一直是个头疼的问题

    不取消就会内存泄露,调用已关闭的activity,造成崩溃.

    当然,现在有RxLifecyle之类的库,很方便.

    这里我简单实现了一个.不过有版本限制.依赖Android自带的Lifecycle

    JApiImpl

    public class JApiImpl implements JApi, LifecycleObserver, ObservableTransformer<String, String> {
    
        public static JApi getApi() {
            return RetrofitUtil.getApi(JApi.class);
        }
    
        public static JApiImpl with(Lifecycle lifecycle) {
            JApiImpl JApiImpl = new JApiImpl();
            lifecycle.addObserver(JApiImpl);
            return JApiImpl;
        }
    
        public static JApiImpl with(Fragment fragment) {
            return with(fragment.getLifecycle());
        }
    
        public static JApiImpl with(AppCompatActivity activity) {
            return with(activity.getLifecycle());
        }
    
        private Disposable disposable;
    
        @Override
        public ObservableSource<String> apply(Observable<String> upstream) {
            return upstream.doOnSubscribe(disposable -> this.disposable = disposable);
        }
    
        private void cancel() {
            if (this.disposable != null && !disposable.isDisposed()) {
                disposable.dispose();
            }
        }
    
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        public void onDestroy() {
            this.cancel();
            Log.i("233", "取消了请求");
        }
    
        @Override
        public Observable<String> post(String url, HashMap<String, RequestBody> params) {
            return getApi().post(url, params).compose(this);
        }
    
        @Override
        public Observable<String> post(String url, String json) {
            return getApi().post(url, json).compose(this);
        }
    
        @Override
        public Observable<String> post(String url, SimpleParams params) {
            return getApi().post(url, params).compose(this);
        }
    
        @Override
        public Observable<String> get(String url, SimpleParams params) {
            return getApi().post(url, params).compose(this);
        }
    
    }
    
    

    实现了JApi,LifecycleObserver,ObservableTransformer

    LifecycleObserver是为了利用现在android自带的Lifecycle实现取消回调

    ObservableTransformer是为了转换Observer.拿到Disposable.

    这么改一下后.请求就可以这样:

                JApiImpl.with(this)
                    .get("/login", SimpleParams.create()
                            .putP("key1", 1)
                            .putP("key2", 2)
                            .putP("key3", 2)
                            .putP("key4", 3)
                    )
                    .compose(JRxCompose.normal())
                    .subscribe(new Consumer<String>() {
                        @Override
                        public void accept(String s) throws Exception {
    
                        }
                    });
    

    添加加密/解密

            NetWorkManager.initKey("私钥", "公钥");//加密解密
    

    设置超时时间

            NetWorkManager.setDefaultTimeOut(20);//秒
    

    设置重试次数

            NetWorkManager.setDefaultRetry(5);//重试次数
    

    设置全局异常统一回调

       NetWorkManager.setExceptionListener(new onExceptionListener() {
                @Override
                public String onError(Throwable throwable) {
                    return null; 
                }
            });
    

    设置添加全局code状态处理

      NetWorkManager.setApiCallBack(new APICallBack() {
                @Override
                public String callback(String code, String resultData) {
                    JsonElement jsonElement = JSONFactory.parseJson(resultData);
                    return JSONFactory.getValue(jsonElement, "message");
                }
            });
    

    设置打开服务器返回msg异常

    如果callback不处理,并打开isOpenApiException,则抛出服务器返回msg信息

    NetWorkManager.setOpenApiException(true);
    

    异常的处理逻辑

        String errorMsg = null;
        //通过code获取注册的接口回调.
        APICallBack apiCallback = NetWorkManager.getApiCallback();
        if (apiCallback != null) {
            String callbackMsg = apiCallback.callback(code, response);
            if (!TextUtils.isEmpty(callbackMsg)) {
                errorMsg = callbackMsg;
            }
        }
    
        //如果callback不处理,并打开isOpenApiException,则抛出服务器返回msg信息
        if (TextUtils.isEmpty(errorMsg) && NetWorkManager.isOpenApiException()) {
            errorMsg = msg;
        }
        //抛出异常,走到onError.
        throw new APIException(code, errorMsg);
    

    解析结果是Object或Array的例子:

            //结果是一个Object
            JApiImpl.with(this)
                    .post("/Login", SimpleParams.create())
                    .compose(JRxCompose.obj(Login.class))
                    .subscribe(new Consumer<Login>() {
                        @Override
                        public void accept(Login login) throws Exception {
    
                        }
                    });
            //结果是集合
            JApiImpl.with(this)
                    .post("/Login", SimpleParams.create())
                    .compose(JRxCompose.array(Login.class))
                    .subscribe(new Consumer<List<Login>>() {
                        @Override
                        public void accept(List<Login> logins) throws Exception {
                            
                        }
                    });
    

    简单的Observer

    这里支持传入CompositeDisposable,添加当前的Disposable,用于取消回调,如果你用了上面的
    JApiImpl,那么这里可以不传CompositeDisposable,这个是我最早实现统一取消回调的逻辑.

    /**
     * @author jlanglang  2016/11/14 17:32
     * @版本 2.0
     * @Change
     */
    public abstract class SimpleObserver<T> implements Observer<T> {
        protected Disposable mDisposable;
        private CompositeDisposable mCompositeDisposable;
    
        public SimpleObserver() {
            this(null);
        }
    
        public SimpleObserver(CompositeDisposable compositeDisposable) {
            mCompositeDisposable = compositeDisposable;
        }
    
        @Override
        public void onSubscribe(@NonNull Disposable d) {
            mDisposable = d;
            try {
                mCompositeDisposable.add(d);
            } catch (Exception ignored) {
    
            }
        }
    
        @Override
        public void onNext(T t) {
            call(t);
        }
    
        @Override
        public void onError(Throwable e) {
         
        }
    
    
        @Override
        public void onComplete() {
    
        }
    
        public abstract void call(@NonNull T t);
    }
    
    

    ToastObserver

    在实际使用的时候,我们一般不会每个请求都弹Toast.
    所以.如果需要默认弹Toast的请求.可以使用这个类.

    /**
     * @author jlanglang  2016/11/14 17:32
     */
    public abstract class ToastObserver<T> extends SimpleObserver<T> {
    
        public ToastObserver() {
            this(null);
        }
    
        public ToastObserver(CompositeDisposable com) {
            super(com);
        }
    
        @Override
        public void onError(Throwable e) {
            String errorMsg = NetWorkErrorFactory.disposeError(e);
            if (!TextUtils.isEmpty(errorMsg)) {
                Toast.makeText(NetWorkManager.getContext(), errorMsg, Toast.LENGTH_SHORT).show();
            }
        }
    }
    

    异常解析工厂

    这个类,其实让我很纠结,因为这个类好像没什么作用.又好像又作用.
    但是太绕了.
    比如在NetWorkTransformer中抛出的APIException,以及初始化设置的onExceptionListener
    都是这里来处理的.
    但不调用这个方法.这个方法就无意义.

    我是在上面的ToastObserver中调用了这个方法.
    你可以自定义这个方法在哪调用.

     /**
         * 异常时处理工厂
         *
         * @param throwable 异常
         * @return 获取异常提示消息
         */
        public static String disposeError(Throwable throwable) {
            Class<? extends Throwable> throwableClass = throwable.getClass();
            //处理Api自定义异常处理,请求是成功的,如果需要特殊处理,使用APICallBack
            if (throwableClass.equals(APIException.class)) {
                return throwable.getMessage();
            }
            //处理error异常,http异常
            onExceptionListener exceptionListener = NetWorkManager.getExceptionListener();
            if (exceptionListener != null) {
                return exceptionListener.onError(throwable);
            }
            return "";
        }
    

    结语

    大致使用就这些了.

    库里还包含了rxbus.

    欢迎大家点赞,留言提建议

    github地址: JRxRetrofit

    交流群:

    Flutter:782978118

    Android:493180098

    相关文章

      网友评论

        本文标题:Android 我的Retrofit+Rxjava封装,不搞花里

        本文链接:https://www.haomeiwen.com/subject/jfdbyctx.html