美文网首页
Retrofit+RxJava2的封装使用

Retrofit+RxJava2的封装使用

作者: Veken_Fly | 来源:发表于2017-11-16 14:14 被阅读0次

    公司上个项目用的是rxjava1.0,最近看了各种rxjava2.0的介绍,自己也摸索着来,所以打算封装一下,用到项目中,与时俱进嘛!先不多逼逼了,直截了当,上货......
    先看一下关于怎么配置Retrofit,这个大家都差不多,就不多解释了。。。base_url直接换成自己公司服务器的地址就可以了
    github地址:https://github.com/Veken/RxJava2Retrofit
    1 封装

    Retrofit配置类 
    /**
     * Retrofit配置
     */
    public class RetrofitConnect {
        private Retrofit retrofit;
        private Service service;
        /**
         * 网络请求超时时间毫秒
         */
        int DEFAULT_TIMEOUT = 20000;
    
        /**
         *   你们公司自己的服务器地址
         */
        public static String BASE_URL = "";
    
        private RetrofitConnect() {
           /* HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);*/
    
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    try {
                        String text = URLDecoder.decode(message, "utf-8");
                        LogUtils.e("OKHttp-----", text);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                        LogUtils.e("OKHttp-----", message);
                    }
                }
            });
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            File cacheFile = new File(Utils.getContext().getCacheDir(), "cache");
            Cache cache = new Cache(cacheFile, 1024 * 1024 * 100); //100Mb
    
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    .readTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
                    .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
                    .addInterceptor(interceptor)
                    .addNetworkInterceptor(new HttpCacheInterceptor())
                    .cache(cache)
                    .build();
    
            Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").serializeNulls().create();
    
            retrofit = new Retrofit.Builder()
                    .client(okHttpClient)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .baseUrl(BASE_URL)
                    .build();
            service = retrofit.create(Service.class);
        }
    
        //  创建单例
        private static class SingletonHolder {
            private static final RetrofitConnect INSTANCE = new RetrofitConnect();
        }
        public static Service getApiService() {
            return SingletonHolder.INSTANCE.service;
        }
    
        class HttpCacheInterceptor implements Interceptor {
    
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (!NetworkUtils.isConnected()) {  //没网强制从缓存读取
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                    LogUtils.d("Okhttp", "no network");
                }
    
    
                Response originalResponse = chain.proceed(request);
                if (NetworkUtils.isConnected()) {
                    //有网的时候读接口上的@Headers里的配置,你可以在这里进行统一的设置
                    String cacheControl = request.cacheControl().toString();
                    return originalResponse.newBuilder()
                            .header("Cache-Control", cacheControl)
                            .removeHeader("Pragma")
                            .build();
                } else {
                    return originalResponse.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=2419200")
                            .removeHeader("Pragma")
                            .build();
                }
            }
        }
    }
    

    接下来第一步封装,把请求的一些网络线程等等封装在一个类SubScriberHandler里面
    并且把post请求的参数进行sha加密,参数可以根据公司自己的要求,自己更改

    public class SubScriberHandler {
    
        /**
         * @param o
         * @param <T>
         */
        public <T> void toSubscribe(Observable<T> o, DefaultObserver observer) {
            o.subscribeOn(Schedulers.io())      //网络耗时操作在io线程处理
                    .unsubscribeOn(Schedulers.io()) //网络耗时操作在io线程处理
                    .observeOn(AndroidSchedulers.mainThread())  //更新数据在主线程
                    .subscribe(observer);
        }
    
        /**
         * 添加共同参数 SHA1加密
         * @param fields
         */
        public void handleFields(Map<String, Object> fields) {
            fields.put("appKey", "00001");
            fields.put("v", "1.0");
            String sessionId = SpConfig.getInstance().getString(Constants.SESSIONID_STRING);
            if(!TextUtils.isEmpty(sessionId))
                fields.put(Constants.SESSIONID_STRING, sessionId);
    
            String sha1 = null;
            try {
                sha1 = SHA1.SHA1(fields);
            } catch (DigestException e) {
                e.printStackTrace();
            }
            fields.put("sign", sha1);
        }
    }
    

    接下来是关于自定义的实现Observer的类DefalutObserver,同时也添加了一个加载数据时候的progressdialog,可以根据公司的需求更改成自己的progressdialog,我这只是简单的调用普通的。各位客官也可以自己看心情来封装

    **
     * @author Veken
     */
    public abstract class DefaultObserver<T extends BaseRespond> implements Observer<T>,ProgressCancelListener {
        private Context context;
        private boolean isAddInStop = false;
        private ProgressDialogHandler mProgressDialogHandler;
        //取消订阅
        private Disposable mDisposable;
    
        public DefaultObserver(Context context, boolean isShowLoading) {
            this.context = context;
            mProgressDialogHandler = new ProgressDialogHandler(context,this,true);
            if (isShowLoading) {
                showProgressDialog();
            }
        }
    
        private void showProgressDialog(){
            if (mProgressDialogHandler != null) {
                mProgressDialogHandler.obtainMessage(ProgressDialogHandler.SHOW_PROGRESS_DIALOG).sendToTarget();
            }
        }
    
        private void dismissProgressDialog(){
            if (mProgressDialogHandler != null) {
                mProgressDialogHandler.obtainMessage(ProgressDialogHandler.DISMISS_PROGRESS_DIALOG).sendToTarget();
                mProgressDialogHandler = null;
            }
        }
    
        @Override
        public void onSubscribe(Disposable d) {
            mDisposable =d;
        }
    
        @Override
        public void onNext(T response) {
            dismissProgressDialog();
            if (response.getResCode().equals("200")) {
                onSuccess(response);
            } else {
                onFail(response);
            }
        }
    
    
        @Override
        public void onError(Throwable e) {
            LogUtils.e("Retrofit", e.getMessage());
    //        dismissProgress();
            dismissProgressDialog();
            if (e instanceof HttpException) {     //   HTTP错误
                onException(ExceptionReason.BAD_NETWORK);
            } else if (e instanceof ConnectException
                    || e instanceof UnknownHostException) {   //   连接错误
                onException(ExceptionReason.CONNECT_ERROR);
            } else if (e instanceof InterruptedIOException) {   //  连接超时
                onException(ExceptionReason.CONNECT_TIMEOUT);
            } else if (e instanceof JsonParseException
                    || e instanceof JSONException
                    || e instanceof ParseException) {   //  解析错误
                onException(ExceptionReason.PARSE_ERROR);
            } else {
                onException(ExceptionReason.UNKNOWN_ERROR);
            }
        }
    
        @Override
        public void onComplete() {
            dismissProgressDialog();
        }
    
        /**
         * 请求成功
         *
         * @param response 服务器返回的数据
         */
        abstract public void onSuccess(T response);
    
        /**
         * 服务器返回数据,但响应码不为200
         *
         * @param response 服务器返回的数据
         */
        public void onFail(T response) {
            String message = response.getResDesc();
            if (TextUtils.isEmpty(message)) {
                ToastUtils.show(R.string.response_return_error);
            } else {
                ToastUtils.show(message);
            }
        }
    
        /**
         * 请求异常
         *
         * @param reason
         */
        public void onException(ExceptionReason reason) {
            switch (reason) {
                case CONNECT_ERROR:
                    ToastUtils.show(R.string.connect_error, Toast.LENGTH_SHORT);
                    break;
    
                case CONNECT_TIMEOUT:
                    ToastUtils.show(R.string.connect_timeout, Toast.LENGTH_SHORT);
                    break;
    
                case BAD_NETWORK:
                    ToastUtils.show(R.string.bad_network, Toast.LENGTH_SHORT);
                    break;
    
                case PARSE_ERROR:
                    ToastUtils.show(R.string.parse_error, Toast.LENGTH_SHORT);
                    break;
    
                case UNKNOWN_ERROR:
                default:
                    ToastUtils.show(R.string.unknown_error, Toast.LENGTH_SHORT);
                    break;
            }
        }
    
        /**
         * 请求网络失败原因
         */
        public enum ExceptionReason {
            /**
             * 解析数据失败
             */
            PARSE_ERROR,
            /**
             * 网络问题
             */
            BAD_NETWORK,
            /**
             * 连接错误
             */
            CONNECT_ERROR,
            /**
             * 连接超时
             */
            CONNECT_TIMEOUT,
            /**
             * 未知错误
             */
            UNKNOWN_ERROR,
        }
    
        /**
         * 取消ProgressDialog的时候,取消对observable的订阅,同时也取消了http请求
         */
        @Override
        public void onCancelProgress() {
            if (!mDisposable.isDisposed()) {
                mDisposable.dispose();
            }
        }
    }
    

    现在就是大家耳熟能详的Service类,这就没什么可说的,你要什么请求,就是什么,比如你要登录就写一个login的service,然后Map中装你需要请求的参数,以此类推。

    /**
     * @author Veken
     */
    public interface Service {
    
    
        /**
         * 登录的service
         * @param fields
         * @return
         */
        @FormUrlEncoded
        @POST(Constants.URLEND)
        Observable<LoginRespond> login(@FieldMap Map<String, Object> fields);
    
    }
    

    现在到了正儿八经的封装了,前面的都是开胃菜,配置都差不多,大同小异,到上真货的时候了

    public class UserInfoRequest extends SubScriberHandler {
    
        private UserInfoBean userInfoBean;
        private Context context;
    
        public UserInfoRequest(Context context,UserInfoBean userInfoBean) {
            this.context = context;
            this.userInfoBean = userInfoBean;
        }
    
        public void login() {
    
            Map<String, Object> fields = new HashMap<>();
            //调用的接口方法,比如login方法
            fields.put("method", "user.login");
            //加密和传一些常用参数
            handleFields(fields);
            //需要传递的参数
            fields.put("phoneNo", userInfoBean.getPhoneNum());
            fields.put("password", userInfoBean.getPwd());
            //申请网络
            Observable observable = RetrofitConnect.getApiService().login(fields);
            toSubscribe(observable, new DefaultObserver(context,true) {
                //数据返回在onNext
                @Override
                public void onSuccess(BaseRespond response) {
                }
    
               //数据返回
                @Override
                public void onNext(@NonNull BaseRespond response) {
                    //将结果封装在javabean的onSuccess方法里面
                    userInfoBean.onSuccess(response);
                }
    
                @Override
                public void onError(Throwable e) {
                    super.onError(e);
                    userInfoBean.onError(e);
                }
            });
        }
    
    }
    
    

    2 调用
    下面就是具体调用了,看一下在MainActivity中怎么简单的调用吧
    实现UserInfoBean,这样可以在重写的方法中传入我们需要的参数,当然也可以不写一个bean,直接用String传也可以,但是习惯了bean,数据处理也在bean中,简单明了。
    初始化你的UserInfoPresent网络请求
    private UserInfoRequest userInfoRequest;
    userInfoRequest= new UserInfoRequest(this,this);
    如果没有实现bean的话,UserInfoPresent()方法中的参数会报错,如果不想调用bean,可以自己简单的修改一下
    剩下的就简单了,在自己想要请求网络的地方,调用 userInfoPresent.login();一句代码就可以了

    public class MainActivity extends BaseActivity implements UserInfoBean {
        private Button btn;
        private UserInfoRequest userInfoRequest;
        private TextView tv;
    
        @Override
        protected int getLayoutId() {
            return R.layout.activity_main;
        }
    
        @Override
        protected void initData(Bundle savedInstanceState) {
        }
    
        @Override
        protected void initView() {
            btn = (Button) findViewById(R.id.btn);
            tv = (TextView) findViewById(R.id.tv);
            userInfoRequest= new UserInfoRequest(this,this);
    
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    userInfoRequest.login();
                }
            });
        }
    
        //传递的用户
        @Override
        public String getPhoneNum() {
            //根据需要,传递相应的数据
            return "登录账号";
        }
    
        //传递的密码
        @Override
        public String getPwd() {
            //根据需要,传递相应的数据
            return "登录密码";
        }
    
        //数据返回
        @Override
        public void onSuccess(Object object) {
            LoginRespond loginRespond = (LoginRespond) object;
            Log.d("登录信息:", loginRespond.getResDesc());
            tv.setText(loginRespond.getData().getTelphone());
        }
    
        @Override
        public void onError(Throwable e) {
    
        }
    }
    

    想必有老铁就问了,如果一个界面有多处需要请求网络的,那该怎么办呢?
    因为我们是通过实现javabean的方法,java是单继承,多实现吗。这不就清楚了
    当然你还可以直接使用

     Map<String, Object> fields = new HashMap<>();
            //调用的接口方法,比如login方法
            fields.put("method", "user.login");
            //加密和传一些常用参数
            handleFields(fields);
            //传递需要传递的参数
            fields.put("phoneNo", userInfoBean.getPhoneNum());
            fields.put("password", userInfoBean.getPwd());
            //申请网络
            Observable observable = RetrofitConnect.getApiService().login(fields);
            toSubscribe(observable, new DefaultObserver(context,true) {
                //数据返回在onNext
                @Override
                public void onSuccess(BaseRespond response) {
                }
    
                @Override
                public void onNext(@NonNull BaseRespond response) {
                    userInfoBean.onSuccess(response);
                }
    
                @Override
                public void onError(Throwable e) {
                    super.onError(e);
                    userInfoBean.onError(e);
                }
            });
    

    初始化UserInfoRequest,就可以了。
    还有很多不足的地方,希望各位老爷批评指正,大家共同进步,自己项目实战过的,不是demo,所以可以直接拿来用,有什么问题,还烦请指教、、、
    PS:没有用到太多的RxJava的操作符,刚接触,还不是很熟悉,还不会灵活运用,见谅!!!
    在这里要感谢那些为我们分享贡献的前辈,感谢他们的辛勤耕耘,才有我们菜鸟的不断进步。
    特此感谢:
    用水管讲解rxjava和retroft使用的:http://www.jianshu.com/p/464fa025229e
    以及这位前辈提供的demo参考:https://github.com/zhpanvip/Retrofit2

    相关文章

      网友评论

          本文标题:Retrofit+RxJava2的封装使用

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