Rx系列<第三十二篇>:RxJava+Retrofit+OkHttp+MVP

本章主要针对RxJavaRetrofitOkHttp结合使用,现在说明一下三者的职责所在。

OkHttp:负责网络请求;
Retrofit:主要负责网络请求接口的封装,结合OkHttp可以处理网络请求的结果;
RxJava:负责网络请求的异步;

(1)权限

网络请求别忘了添加网络权限


(2)依赖
  • RxJava依赖
implementation 'io.reactivex.rxjava2:rxjava:2.1.3'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'

或者

implementation 'com.jakewharton.rxbinding3:rxbinding:3.0.0-alpha2'

如果使用rxbinding,就添加rxbinding相关依赖,rxbinding依赖本身支持rxjava和rxandroid,所以如果添加rxbinding依赖就可以去除rxjava和rxandroid依赖了。

  • okhttp3依赖
implementation 'com.squareup.okhttp3:okhttp:3.12.2'

//日志拦截器依赖
implementation 'com.squareup.okhttp3:logging-interceptor:3.5.0'
  • retrofit依赖
implementation 'com.squareup.retrofit2:retrofit:2.5.0'

//gson转换器依赖
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
  • RxJava和Retrofit混用的适配器
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
  • autodispose依赖
implementation 'com.uber.autodispose:autodispose-android-archcomponents:1.0.0-RC2'
  • 其它辅助依赖
//gson依赖
implementation 'com.google.code.gson:gson:2.8.5'
(3)RxJava介绍

点击某按钮,请求网络接口,要求防抖动(防止不一小心点击两次,导致没必要的网络请求),RxJava可以实现按钮防抖动。

    RxView.clicks(findViewById(R.id.bt))
            .throttleFirst(2, TimeUnit.SECONDS)
            //AutoDispose的关键语句
            .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
            .subscribe(new Consumer() {
                @Override
                public void accept(Unit unit) throws Exception {
                    //获取新闻
                    mainPresenter.getWeather();

                }
            });

throttleFirst表示2秒内,只处理第一次点击的响应;
AutoDispose是为了防止内存泄漏;

RxJava还可以和Retrofit共同完成网络请求。

/**
 * 获取天气预报
 */
public void getWeather(ResultCallBack callBack){
    RetrofitUtils.getInstance().getDataFromAPI(retrofitAPI.getWeather(), callBack);
}


/**
 * 通用方法
 * @param observable
 * @param 
 */
public  void getDataFromAPI(Observable observable, final ResultCallBack callBack){

    //绑定Activity的生命周期
    callBack.autoDispose(observable);

    observable
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer() {
                @Override
                public void onSubscribe(Disposable d) {
                    //开始请求

                    callBack.startRequest();

                }

                @Override
                public void onNext(T t) {
                    //成功
                    callBack.success(t);

                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    //失败
                    Log.d("aaa", "onFailure:"+e.getCause() + "\n" + e.getMessage());

                    if (e instanceof SocketTimeoutException) {
                        callBack.failed("网络中断,请检查您的网络状态!");
                    } else if (e instanceof ConnectException) {
                        callBack.failed("网络中断,请检查您的网络状态!");
                    }else{
                        callBack.failed("未知异常!");
                    }
                }

                @Override
                public void onComplete() {
                    //结束请求

                    callBack.requestComplete();

                }
            });
}
(4)Retrofit介绍

单独使用Retrofit,网络请求的返回值类型是Call,与RxJava结合使用后返回值变成了observable,这样做的好处是:

  • 可以方便的控制线程
  • 可以知道网络请求什么时候开始以及什么时候结束

另外,OkHttp可以设置网络超时以及其他配置。

Retrofit在之前的文章中已经介绍过了,因此这里直接跳过,等下直接贴代码。

(5)MVP介绍

MVP模式请先看一下这篇博客

Andorid之MVP模式

这篇博客是最简单的MVP模式了,在实际项目中往往更加复杂,但是,复杂并不可怕,可怕的是你不知道怎么使用MVP。

MVP模式一般流向是:View-->Presenter-->Model,这里最好不要逆向,或者禁止逆向。

这个流向大致的意思是View直接访问Presenter,Presenter直接访问Model,那么问题来了:

  • Presenter怎么访问View?

Activity(Fragment)就是MVP的View,该Activity(Fragment)会实现一个IView接口,Presenter与IView具有依赖性,Presenter通过IView可以间接执行Activity(Fragment)的IView回调。

  • Model怎么访问Presenter?

通过CallBack访问,等下贴下代码就知道了。

  • Model怎么访问View?

先通过CallBack访问Presenter,再让Presenter通过IView访问Activity(Fragment)。

(6)完整封装

这里直接贴代码了。

WeatherBean.java(这是新闻类的Bean,网络请求之后数据装载类)

public class WeatherBean {

    /**
     * status : 201
     * message : APP被用户自己禁用,请在控制台解禁
     */

    private int status;
    private String message;

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

ResultCallBack.java(这是网络请求结果返回的callback)

public interface ResultCallBack {

    //开始请求
    void startRequest();

    //请求成功
    void success(T t);

    //请求失败
    void failed(String error);

    //请求完成
    void requestComplete();

    //自动绑定生命周期
    void autoDispose(Observable observable);

}

RetrofitAPI.java(Retrofit接口类,这里会防止所有的网络请求接口)

public interface RetrofitAPI {

    @GET("weather?location=jiaxing&output=json&ak=5slgyqGDENN7Sy7pw29IUvrZ")
    Observable getWeather();

}

RetrofitUtils.java(Retrofit网络请求工具类,这是通用的)

public class RetrofitUtils {

    private RetrofitAPI retrofitAPI;

    private String BASE_URL = "http://api.map.baidu.com/telematics/v3/";

    private RetrofitUtils(){
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)//设置连接超时时长
                .readTimeout(20, TimeUnit.SECONDS)//设置读超时时长
                .writeTimeout(20, TimeUnit.SECONDS)//设置写超时时长
                .addInterceptor(getHttpLoggingInterceptor())//添加日志拦截器
                .build();
        Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(new Gson()))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(client)
                .build();
        retrofitAPI = retrofit.create(RetrofitAPI.class);
    }

    static class SingleHolder{
        public static RetrofitUtils instance = new RetrofitUtils();
    }

    public static RetrofitUtils getInstance(){
        return RetrofitUtils.SingleHolder.instance;
    }

    /**
     * 创建日志拦截器
     * @return
     */
    private HttpLoggingInterceptor getHttpLoggingInterceptor() {
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(
                new HttpLoggingInterceptor.Logger() {

                    @Override
                    public void log(String message) {
                        Log.e("RetrofitUtils", "log = " + message);
                    }

                });
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return loggingInterceptor;
    }

    public RetrofitAPI getRetrofitAPI(){
        return retrofitAPI;
    }


    /**
     * 通用方法
     * @param observable
     * @param 
     */
    public  void getDataFromAPI(Observable observable, final ResultCallBack callBack){

        //绑定Activity的生命周期
        callBack.autoDispose(observable);

        observable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        //开始请求

                        callBack.startRequest();

                    }

                    @Override
                    public void onNext(T t) {
                        //成功
                        callBack.success(t);

                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        //失败
                        Log.d("aaa", "onFailure:"+e.getCause() + "\n" + e.getMessage());

                        if (e instanceof SocketTimeoutException) {
                            callBack.failed("网络中断,请检查您的网络状态!");
                        } else if (e instanceof ConnectException) {
                            callBack.failed("网络中断,请检查您的网络状态!");
                        }else{
                            callBack.failed("未知异常!");
                        }
                    }

                    @Override
                    public void onComplete() {
                        //结束请求

                        callBack.requestComplete();

                    }
                });
    }

}

CarModel.java(MVP模式的Model,用于处理非UI操作,一般用于处理网络请求)

public class CarModel {

    private RetrofitAPI retrofitAPI;


    public CarModel(){
        retrofitAPI = RetrofitUtils.getInstance().getRetrofitAPI();
    }

    /**
     * 获取天气预报
     */
    public void getWeather(ResultCallBack callBack){
        RetrofitUtils.getInstance().getDataFromAPI(retrofitAPI.getWeather(), callBack);
    }
}

BasePresenter.java(MVP模式的Presenter的基类,主要负责处理一些通用的逻辑)

/**
 * Presenter基类
 * @param 
 */
public class BasePresenter {

    /**
     * 绑定的view
     */
    private V mvpView;

    /**
     * 绑定view
     */
    public void attachView(V mvpView) {
        this.mvpView = mvpView;
    }
    /**
     * 销毁view
     */
    public void detachView() {
        this.mvpView = null;
    }
    /**
     * 是否与View建立连接
     */
    public boolean isViewAttached(){
        return mvpView != null;
    }

    /**
     * 获取连接的view
     */
    public V getView(){
        return mvpView;
    }
}

MainPresenter.java(MVP模式的Presenter)

public class MainPresenter extends BasePresenter {

    private CarModel carModel;

    public MainPresenter(){
        carModel = new CarModel();
    }

    /**
     * 获取天气预报
     * @param
     */
    public void getWeather(){
        carModel.getWeather(new ResultCallBack() {
            @Override
            public void startRequest() {
                getView().loadingDialogShow("请稍等...");
            }

            @Override
            public void success(WeatherBean weatherBean) {
                if(weatherBean != null){
                    getView().setResult(weatherBean.getMessage());
                }
            }

            @Override
            public void failed(String error) {
                getView().setResult(error);
            }

            @Override
            public void requestComplete() {
                getView().loadingDialogDismiss();
            }

            @Override
            public void autoDispose(Observable observable) {
                //AutoDispose的关键语句
                getView().autoDispose(observable);
            }
        });
    }

}

IBaseView.java(MVP模式的View的基类,可以在Activity的基类中实现)

/**
 * 所有UI通用的View操作
 */
public interface IBaseView {

    /**
     * 显示等待对话框
     */
    void loadingDialogShow(String msg);

    /**
     * 关闭等待对话框
     */
    void loadingDialogDismiss();

    /**
     * 显示提示
     * @param msg
     */
    void showToast(String msg);

    /**
     * 获取上下文
     * @return 上下文
     */
    Context getContext();

    /**
     * Observable绑定生命周期
     * @param observable
     * @return
     */
    void autoDispose(Observable observable);
}

IMainView.java(MVP模式的View)

public interface IMainView extends IBaseView{

    void setResult(String result);

}

BaseActivity.java(所有Activity的基类,包含网络进度条、AutoDispose、Toast、网络请求等待对话框)

public abstract class BaseActivity extends AppCompatActivity implements IBaseView {

    private AlertDialog loadingDialog;

    protected Toolbar toolbar;
    private ViewFlipper mContentView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //初始化布局
        setContentView(R.layout.layout_base);
        mContentView = (ViewFlipper) findViewById(R.id.layout_container);
        toolbar = (Toolbar) findViewById(R.id.base_tool_bar);

        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 1);
        mContentView.addView(getRootView(), lp);

        //初始化基类数据
        initBaseData();
        //初始化控件
        initView();
        //初始化数据
        initData();
        //初始化监听
        initListener();
    }

    /**初始化基类数据*/
    private void initBaseData(){}{
    }
    /**初始化布局*/
    protected abstract View getRootView();
    /**初始化控件*/
    protected abstract void initView();
    /**初始化数据*/
    protected abstract void initData();
    /**初始化点击事件*/
    protected abstract void initListener();

    /**
     * 启动Activity
     * @param clazz
     */
    protected void startActivity(Class clazz){
        Intent in = new Intent(this,clazz);
        startActivity(in);
    }

    @Override
    public void loadingDialogShow(String msg) {
        TextView tipTextView = null;
        LayoutInflater inflater = LayoutInflater.from(this);
        View view = inflater.inflate(R.layout.loading_dialog, null);// 得到加载view

        if (loadingDialog == null) {
            ImageView imageView = view.findViewById(R.id.img);
            tipTextView = view.findViewById(R.id.tipTextView);// 提示文字
            // 加载动画
            Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.loading_animation);
            // 使用ImageView显示动画
            imageView.startAnimation(hyperspaceJumpAnimation);
            tipTextView.setText(msg);// 设置加载信息

            AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.loading_dialog);
            loadingDialog =builder.create();
            builder.setCancelable(false);
        }

        if (!loadingDialog.isShowing()) {
            loadingDialog.show();
            loadingDialog.getWindow().setContentView(view);
        }
    }

    @Override
    public void loadingDialogDismiss() {
        if (loadingDialog != null && loadingDialog.isShowing()) {
            try {
                loadingDialog.dismiss();
                loadingDialog = null;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public Context getContext() {
        return this;
    }

    @Override
    public void autoDispose(Observable observable) {
        //AutoDispose的关键语句
        observable.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)));
    }

    @Override
    protected void onDestroy() {
        //关闭进度条
        super.onDestroy();
        loadingDialogDismiss();
    }
}

MainActivity.java

public class MainActivity extends BaseActivity implements IMainView {

    private MainPresenter mainPresenter;
    private TextView result_text;

    @Override
    protected View getRootView() {
        return LayoutInflater.from(this).inflate(R.layout.activity_main, null);
    }

    @Override
    protected void initView() {
        result_text = findViewById(R.id.result_text);
    }

    @Override
    protected void initData() {
        mainPresenter = new MainPresenter();
        mainPresenter.attachView(this);
    }

    @Override
    protected void initListener() {

        RxView.clicks(findViewById(R.id.bt))
                .throttleFirst(2, TimeUnit.SECONDS)
                //AutoDispose的关键语句
                .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
                .subscribe(new Consumer() {
                    @Override
                    public void accept(Unit unit) throws Exception {
                        //获取新闻
                        mainPresenter.getWeather();

                    }
                });
    }

    @Override
    public void setResult(String result) {
        //显示结果
        result_text.setText(result);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if(mainPresenter.isViewAttached()){
            mainPresenter.detachView();
        }
    }
}

loading_animation.xml




    


loading_dialog.xml




    

    


layout_base.xml




    

    

    


activity_main.xml




    
        

图片:

aliwx_img_loading.png

style:



[本章完...]

你可能感兴趣的:(Rx系列<第三十二篇>:RxJava+Retrofit+OkHttp+MVP)