Android_MVP小封装

作者: 间歇性丶神经病患者 | 来源:发表于2017-01-19 16:19 被阅读346次

    MVP是个好东西,可是最近项目一直用的是mvc模式,先马克下之前鼓捣过的mvp框架,过年回家再用它重构下代码。

    先上依赖库####

      compile 'io.reactivex:rxandroid:1.2.1'  
      compile 'com.squareup.okhttp3:okhttp:3.3.1'  
      compile 'io.reactivex:rxandroid:1.1.0'  
      compile 'io.reactivex:rxjava:1.1.0'  
      compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'  
      compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'  
      compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'  
      compile 'com.android.support:design:24.2.1'  
      compile 'com.android.support:recyclerview-v7:24.2.1'  
      compile 'com.android.support:cardview-v7:24.2.1'  
      compile 'com.jakewharton:butterknife:7.0.1'  
      compile 'com.github.bumptech.glide:glide:3.7.0'  
      compile 'com.github.chrisbanes.photoview:library:1.2.3'  
    

    建议写死依赖的版本号,而不要使用“+”,避免版本升级带了一些奇葩的问题。

    依赖retrolambda####

    在app.build依赖

        apply plugin: 'me.tatarka.retrolambda'  
    

    再加上

        compileOptions {  
        sourceCompatibility JavaVersion.VERSION_1_8  
         targetCompatibility JavaVersion.VERSION_1_8  
       }  
    

    然后在整个项目的build文件上面加入:

          classpath 'me.tatarka:gradle-retrolambda:3.2.5' 
    

    OK,到这里我们的环境搭建就完成了


    首先我们看下项目的目录结构:

    base文件

    BaseContract(基本的文件类,我们可以在里面写上view层,model层,Presenter层的interface)

      /**
       * Created by Ly on 2016/11/2.
       */
    
      public class BaseContract  {
    }
    

    BaseModel(基本的model层,所有耗时操作应该写在model层中)

      /**
       * Created by Ly on 2016/11/2.
       */
    
      public interface BaseModel {
      }
    

    BaseView层(写入跟用户交互的方法集合类,比如showTosast,showDialog)

        /**
       * Created by Ly on 2016/11/2.
         */
    
      public interface BaseView {
          void TsShow(String msg);
      }
    

    看下我们的基本baseActivity.java:

    package com.Ly.BaseJustTalk.base;
    
    import android.app.ProgressDialog;
    import android.content.Context;
    import android.content.Intent;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.annotation.Nullable;
    import android.support.design.widget.AppBarLayout;
    import android.support.v4.widget.SwipeRefreshLayout;
    import android.support.v7.app.ActionBar;
    import android.support.v7.app.AppCompatActivity;
    import android.support.v7.widget.Toolbar;
    import android.text.TextUtils;
    import android.util.TypedValue;
    import android.view.MenuItem;
    import android.widget.Toast;
    
    import com.Ly.BaseJustTalk.R;
    
    import butterknife.ButterKnife;
    
    /**
     * Created by Ly on 2017/1/12.
     */
    public abstract class BaseActivity<V, T extends BasePresenter<V>> extends AppCompatActivity {
    
        protected T mPresenter;
        private SwipeRefreshLayout mRefreshLayout;
        private AppBarLayout mAppBar;
        private Toolbar mToolbar;
        private ProgressDialog mProgressBar;
        protected Context mContext;
        private boolean mIsRequestDataRefresh = false;
    
        private static final String EXTRA_KEY = "extra";
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            dogetExtra();
            mContext = this;
            // 允许为空,不是所有的页面都要实现这个模式
            if (createPresenter() != null) {
                mPresenter = createPresenter();
                mPresenter.attachView((V) this);
            }
            setContentView(provideContentViewId());
            ButterKnife.bind(this);
    
            mAppBar = findViewById(R.id.app_bar_layout);
            mToolbar = (Toolbar) findViewById(R.id.toolbar);
            if (mToolbar != null && mAppBar != null) {
                setSupportActionBar(mToolbar); //把Toolbar当做ActionBar给设置
    
                if (canBack()) {
                    ActionBar actionBar = getSupportActionBar();
                    if (null != actionBar) {
                        //设置ActionBar一个返回箭头,主界面没有,次级界面有
                        actionBar.setDisplayHomeAsUpEnabled(true);
                    }
                    if (Build.VERSION.SDK_INT >= 21) {
                        //Z轴浮动
                        mAppBar.setElevation(10.6F);
                    }
                }
            }
            if (isSetRefresh()) {
                setupSwipeRefresh();
            }
        }
    
    
        public static void doStartActivity(Context context, Bundle bundle, Class<?> clz) {
            Intent intent = new Intent(context, clz);
            if (bundle != null) {
                intent.putExtra(EXTRA_KEY, bundle);
            }
            context.startActivity(intent);
        }
    
    
        protected abstract void dogetExtra();
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // 此时android.R.id.home即为返回箭头
            if (item.getItemId() == android.R.id.home) {
                onBackPressed();
                finish();
                return true;
            } else {
                return super.onOptionsItemSelected(item);
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (mPresenter != null) {
                mPresenter.detachView();
            }
        }
    
        /**
         * 生成下拉刷新
         */
        private void setupSwipeRefresh() {
            mRefreshLayout = findViewById(R.id.swipe_refresh);
            if (null != mRefreshLayout) {
                mRefreshLayout.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary);
                mRefreshLayout.setProgressViewOffset(true,
                        0,
                        (int) TypedValue.applyDimension
                                (TypedValue.COMPLEX_UNIT_DIP, 24, getResources()
                                        .getDisplayMetrics()));
            }
        }
    
    
        /**
         * 设置刷新
         *
         * @param requestDataRefresh
         */
        public void setRefresh(boolean requestDataRefresh) {
            if (mRefreshLayout == null) {
                return;
            }
            if (!requestDataRefresh) {
                mIsRequestDataRefresh = false;
                mRefreshLayout.postDelayed(() -> {
                    if (mRefreshLayout != null) {
                        mRefreshLayout.setRefreshing(false);
                    }
                }, 1000);
            } else {
                mRefreshLayout.setRefreshing(true);
            }
        }
    
    
        /**
         * 数据刷新
         */
        public void requestDataRefresh() {
            mIsRequestDataRefresh = true;
        }
    
        /**
         * 判断当前页面是否可以返回,
         * 主界面不可以返回  子界面可以放回
         *
         * @return
         */
        public boolean canBack() {
            return false;
        }
    
        /**
         * 判断子Activity是否需要上下拉刷新功能
         *
         * @return
         */
        public Boolean isSetRefresh() {
            return false;
        }
    
        /**
         * 创建P
         *
         * @return
         */
        protected abstract T createPresenter();
    
        /**
         * 引入布局文件
         *
         * @return
         */
        protected abstract int provideContentViewId();
    
        protected void ShowTs(String msg) {
            Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
        }
    
    
        protected void ShowDialog() {
            ShowDialog(null);
        }
    
        protected void ShowDialog(String msg) {
            if (TextUtils.isEmpty(msg)) {
                msg = getString(R.string.loading);
            }
            mProgressBar = ProgressDialog.show(this, null, msg);
        }
    
        protected void DissDialog() {
            if (mProgressBar != null && mProgressBar.isShowing()) {
                mProgressBar.dismiss();
            }
        }
    }
    
    

    相对应的BaseFragment.java 代码如下:

    package com.Ly.BaseJustTalk.base;
    
    import android.content.Context;
    import android.os.Bundle;
    import android.support.v4.app.Fragment;
    import android.support.v4.widget.SwipeRefreshLayout;
    import android.util.TypedValue;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import com.Ly.BaseJustTalk.R;
    
    import butterknife.ButterKnife;
    
    /**
    * Created by Ly on 2011/1/12.
    */
    
    public abstract class BaseFragment<V, T extends BasePresenter<V>> extends Fragment {
       protected Context mContext;
       protected T mPresenter;
    
       private boolean mIsRequestDataRefresh = false;
       private SwipeRefreshLayout mRefreshLayout;
    
       @Override
       public void onCreate(Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
           mContext = getActivity();
           mPresenter = createPresenter();
           mPresenter.attachView((V) this);
       }
    
       @Override
       public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
           View rootView = inflater.inflate(createViewLayoutId(), container, false);
           ButterKnife.bind(this, rootView);
           initView(rootView);
           if (isSetRefresh()) {
               setupSwipeRefresh(rootView);
           }
           return rootView;
       }
    
       @Override
       public void onDestroy() {
           super.onDestroy();
           mPresenter.detachView();
       }
    
       private void setupSwipeRefresh(View view) {
           mRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh);
           if (mRefreshLayout != null) {
               mRefreshLayout.setColorSchemeResources(R.color.refresh_progress_1,
                       R.color.refresh_progress_2, R.color.refresh_progress_3);
               mRefreshLayout.setProgressViewOffset(true, 0, (int) TypedValue
                       .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()));
               mRefreshLayout.setOnRefreshListener(this::requestDataRefresh);
           }
       }
    
       public void requestDataRefresh() {
           mIsRequestDataRefresh = true;
       }
    
    
       public void setRefresh(boolean requestDataRefresh) {
           if (mRefreshLayout == null) {
               return;
           }
           if (!requestDataRefresh) {
               mIsRequestDataRefresh = false;
               mRefreshLayout.postDelayed(() -> {
                   if (mRefreshLayout != null) {
                       mRefreshLayout.setRefreshing(false);
                   }
               }, 1000);
           } else {
               mRefreshLayout.setRefreshing(true);
           }
       }
    
       protected abstract T createPresenter();
    
       protected abstract int createViewLayoutId();
    
       protected void initView(View rootView) {
       }
    
       public Boolean isSetRefresh() {
           return true;
       }
    }
    
    

    Ok,直接看实例代码来理解,就用登录界面的吧。

    登录界面的包目录

    其中LoginActiviy为用户能看到的界面;
    Contract是mvp的协议层;Model为数据处理层;Presenter可以理解为桥梁,负责沟通连接M层和V层。

    在我的理解里的MVP是这个意思:我们可以看到,这个类持有了View和Model两个模块,在方法体里面,我们调用了model的方法去做耗时,在结果方法体里面我们调用了view的方法去修改UI,同时presenter这个模块又被view持有了,view可以在声明周期里面去调用特定的方法,view和presenter相互沟通,view和model完全隔离,presenter调控model,presenter沟通全局。

    看下我们的登录界面:
    activity_login.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1.5"
            android:gravity="center"
            android:text="@string/text_welcome"
            android:textSize="25sp" />
    
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_marginLeft="@dimen/margin_left"
            android:layout_marginRight="@dimen/margin_right"
            android:layout_weight="3"
            android:orientation="vertical">
    
            <android.support.design.widget.TextInputLayout
                android:id="@+id/til_username"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
    
                <EditText
                    android:id="@+id/et_username"
                    style="@style/edit_style"
                    android:inputType="text"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/text_username" />
            </android.support.design.widget.TextInputLayout>
    
            <android.support.design.widget.TextInputLayout
                android:id="@+id/til_password"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="@dimen/margin6">
    
                <EditText
                    android:id="@+id/et_password"
                    style="@style/edit_style"
                    android:inputType="textPassword"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:hint="@string/text_password" />
            </android.support.design.widget.TextInputLayout>
    
            <Button
                android:id="@+id/bt_login"
                style="@style/button_style"
                android:layout_width="match_parent"
                android:layout_height="@dimen/button_height"
                android:layout_marginTop="@dimen/margin20"
                android:text="@string/text_login_reg" />
        </LinearLayout>
    </LinearLayout>
    

    LoginContract.java

    package com.Ly.BaseJustTalk.ui.activity.Login;
    
    import com.Ly.BaseJustTalk.base.BaseModel;
    import com.Ly.BaseJustTalk.base.BaseView;
    
    /**
     * Created by Ly on 2017/1/16.
     */
    public class LoginContract {
    
    
        interface LoginView extends BaseView {
            String getUserName();
    
            String getUserPass();
    
            //            userName错误后进行提示
            void setUserNameErr(String errMsg);
    
            //            密码错误后进行提示
            void setPassErr(String errMsg);
    
            void doJustalkLogin();
    
            void doLoginFial();
        }
    
    
        interface LoginModel extends BaseModel {
    
            /**
             * @param userName
             * @param Pass
             * @return 0 合法账户密码 给予执行下一步
             * -1 用户名为空
             * -2 用户密码为空
             * -3 用户名不合法
             * -4 用户密码不合法
             */
            int isRightUserNamePass(String userName, String Pass);
    
            /**
             * 进行justalk的登录
             *
             * @param userName
             * @param pass
             * @return
             */
            boolean doJustalkLogin(String userName, String pass);
        }
    
    
        interface LoginPresenter {
            //        验证用户输入的信息
            void doVerificationInfo();
    
            //          验证正确后进行登录
            void doJustalkLogin();
        }
    }
    
    

    LoginModel.java

    package com.Ly.BaseJustTalk.ui.activity.Login;
    
    import android.text.TextUtils;
    import android.util.Log;
    
    import com.Ly.BaseJustTalk.R;
    import com.Ly.BaseJustTalk.application.LyApplication;
    import com.justalk.cloud.juslogin.LoginDelegate;
    
    /**
     * Created by Administrator on 2017/1/16.
     */
    public class LoginModel implements LoginContract.LoginModel {
    
    
        /**
         * 验证账号合法性
         *
         * @param userName
         * @param Pass
         * @return 0 合法账户密码 给予执行下一步
         * -1 用户名为空
         * -2 用户密码为空
         * -3 用户名不合法
         * -4 用户密码不合法
         */
        @Override
        public int isRightUserNamePass(String userName, String Pass) {
            if (TextUtils.isEmpty(userName)) {
                return -1;
            } else if (TextUtils.isEmpty(Pass)) {
                return -2;
            } else if (userName.length() < 4 || userName.length() > 12) {
                return -3;
            } else if (Pass.length() < 6 || Pass.length() > 12) {
                return -4;
            } else
                return 0;
        }
    
        @Override
        public boolean doJustalkLogin( String userName, String pass) {
            if (LoginDelegate.getInitState() == LoginDelegate.InitStat.MTC_INIT_FAIL) {
                return false;
            }
            String server = LyApplication.getInstance().getString(R.string.JusTalkCloud_network_address);
            String network = null;
            if (!server.startsWith("sudp:")) {
                network = server;
                server = "sarc:arc@AccessEntry:99";
                Log.e("testtest", server);
            }
            if (LoginDelegate.login(userName, pass, server, network)) {
                return true;
            }
            return false;
        }
    }
    
    

    LoginPresenter.java

    package com.Ly.BaseJustTalk.ui.activity.Login;
    
    import com.Ly.BaseJustTalk.base.BasePresenter;
    
    /**
     * Created by Ly on 2017/1/16.
     */
    public class LoginPresenter extends BasePresenter<LoginContract.LoginView> implements
            LoginContract.LoginPresenter {
        private LoginContract.LoginView loginView;
        private LoginContract.LoginModel loginModel;
    
        public LoginPresenter(LoginContract.LoginView loginView) {
            this.loginView = loginView;
            loginModel = new LoginModel();
        }
    
        @Override
        public void doVerificationInfo() {
            int resultcode = this.loginModel.isRightUserNamePass(this.loginView.getUserName(), this.loginView.getUserPass());
            switch (resultcode) {
                case -1:
                    this.loginView.setUserNameErr("请输入用户名");
                    break;
                case -2:
                    this.loginView.setPassErr("请输入用户密码");
                    break;
                case -3:
                    this.loginView.setUserNameErr("请检查用户名格式或长度");
                    break;
                case -4:
                    this.loginView.setPassErr("请检查密码格式或长度");
                    break;
                case 0:
                    this.loginView.setUserNameErr(null);
                    this.loginView.setPassErr(null);
                    this.loginView.doJustalkLogin();
                    break;
                default:
                    this.loginView.TsShow("未知错误");
                    break;
            }
        }
    
        @Override
        public void doJustalkLogin() {
            boolean isLoginSuccess = this.loginModel.doJustalkLogin(this.loginView.getUserName(), this.loginView.getUserPass());
            if (!isLoginSuccess) {
                this.loginView.doLoginFial();
            }
        }
    }
    
    

    LoginActivity.java

    package com.Ly.BaseJustTalk.ui.activity.Login;
    
    import android.os.Bundle;
    import android.support.design.widget.TextInputLayout;
    import android.util.Log;
    import android.widget.Button;
    import android.widget.EditText;
    
    import com.Ly.BaseJustTalk.R;
    import com.Ly.BaseJustTalk.base.BaseActivity;
    import com.Ly.BaseJustTalk.ui.activity.MainActivity;
    import com.Ly.BaseJustTalk.utils.Signer;
    import com.justalk.cloud.juslogin.LoginDelegate;
    import com.justalk.cloud.lemon.MtcCli;
    import com.justalk.cloud.lemon.MtcCliConstants;
    
    import butterknife.Bind;
    import butterknife.OnClick;
    
    /**
     * Created by Ly on 2017/1/16.
     */
    public class LoginActivity extends BaseActivity<LoginContract.LoginView, LoginPresenter>
            implements LoginContract.LoginView, LoginDelegate.Callback {
        @Bind(R.id.et_username)
        EditText etUsername;
        @Bind(R.id.til_username)
        TextInputLayout tilUsername;
        @Bind(R.id.et_password)
        EditText etPassword;
        @Bind(R.id.til_password)
        TextInputLayout tilPassword;
        @Bind(R.id.bt_login)
        Button btLogin;
    
    
        private LoginContract.LoginPresenter loginPresenter = new LoginPresenter(this);
    
        @OnClick(R.id.bt_login)
        void toLogin() {
            loginPresenter.doVerificationInfo();
        }
    
        @Override
        protected LoginPresenter createPresenter() {
            return new LoginPresenter(this);
        }
    
        @Override
        protected int provideContentViewId() {
            return R.layout.activity_login;
        }
    
        @Override
        public void TsShow(String msg) {
            ShowTs(msg);
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            LoginDelegate.setCallback(this);
        }
    
    
        @Override
        protected void dogetExtra() {
    
        }
    
    
        @Override
        public String getUserName() {
            return etUsername.getText().toString().trim();
        }
    
        @Override
        public String getUserPass() {
            return etPassword.getText().toString().trim();
        }
    
        @Override
        public void setUserNameErr(String errMsg) {
            tilUsername.setError(errMsg);
        }
    
        @Override
        public void setPassErr(String errMsg) {
            tilPassword.setError(errMsg);
        }
    
        @Override
        public void doJustalkLogin() {
            ShowDialog();
            if (MtcCli.Mtc_CliGetState() != MtcCliConstants.EN_MTC_CLI_STATE_LOGINED) {
                this.loginPresenter.doJustalkLogin();
            } else {
                MainActivity.doStartActivity(mContext, null, MainActivity.class);
            }
        }
    
        @Override
        public void doLoginFial() {
            ShowTs(getString(R.string.tips_login_fail));
        }
    
        @Override
        public void mtcLoginOk() {
            MainActivity.doStartActivity(mContext, null, MainActivity.class);
        }
    
        @Override
        public void mtcLoginDidFail() {
            ShowTs(getString(R.string.tips_login_fail_justalk));
        }
    
        @Override
        public void mtcLogoutOk() {
    
        }
    
        @Override
        public void mtcLogouted() {
    
        }
    
        @Override
        public void mtcAuthRequire(String s, String s1) {
            Log.e("LHT", "mtcAuthRequire: " + s + "----" + s1);
            String key =
                    "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
                            "tRPBKBjUTEQwaKEjPy8YnX1bUODPB+7hto8KeGJbnCdCcnJdLxPFE7ld1skKIyPi" +
                            "YkyHj73JqA41ntHML2LNqw5Mhs1pewE4QLCu6icIUNtH8+bL53EhVnfdzwIDAQAB" +
                            "AoGAA6i6c5xHEGfKzoDHQJgiC5X9ZFAtES5AG3IMJmtF9flQyeoeDzRit+/FwNXi" +
                            "M1CKohnvLAJTvPs/8TBp5us4rabQ5Hnp+ylr7I2IbYIP2LV6TKkiTq/fBOJBxZiw" +
                            "qs0tjXxRZnC2IWqoCt/ciE4DXQIYVV3gYMRcKae5KZ3F2LECQQDqL4Sd2xyG0FsW" +
                            "cKwrlFRQ1cfFrSF/jmm2onkCZgDfq0R5aIGewpbTciLj8rf/Zq0XgAmCa3qQYo6M" +
                            "7G0OgIXTAkEAxbIC2xJocvPfEFbUd+hEWDFl/3LtQWZSHVLx9SXLXWSRY4/3dyRM" +
                            "6L78eQ2yWIVF4pxJrIHTbJqhxItlVM/elQJBAJ3jRZ0L8hKufQsHEf0btzD8wQB0" +
                            "doZCZOF+bumADgy+sp7MJ7/636dVZ1KZ/RWTixWx/DdS8UJRQFygtfI2EoMCQHky" +
                            "4tFPfb1LiStJMES6nnu6/R8YZB++DQVxPmjeXMjKyN9S+ZGPLZ9axwmnvfjK68c7" +
                            "rWcWyHlCa35FP0A5l+kCQB5cEu5Au1RkY9XfUodKmFhlCvdY8Ig0JgZ8DC6m+A31" +
                            "o4xrCoGHiPldKdCo0I7gQ4WMvoVNHCQyNv5qcw9t7uk=";
            String code = Signer.signWithKey(key, s, s1, 3600);
            LoginDelegate.promptAuthCode(code);
        }
    
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            LoginDelegate.logout();
        }
    }
    
    

    更新 这个框架里面的循环嵌套的方法

    
     final String account = "111_111_1111", password = "1234556";
            HttpRequest.getApiService().doRegister(account, password).concatMap(new Function<RegisterBean, Flowable<LoginUserBean>>() {
                @Override
                public Flowable<LoginUserBean> apply(RegisterBean registerBean) throws Exception {
                    if (registerBean.getStatus().equals(ErrCodeMessage.statusSuc)) {
                        XLog.e(registerBean.getMessage());
                        return HttpRequest.getApiService().doLogin(account, password);
                    } else {
                        return Flowable.empty();
                    }
                }
            }).compose(XApi.<LoginUserBean>getScheduler()).compose(XApi.<LoginUserBean>getApiTransformer())
                    .compose(this.<LoginUserBean>bindToLifecycle()).subscribe(new ApiSubscriber<LoginUserBean>() {
                @Override
                protected void onFail(NetError error) {
                    XLog.e("xxxxxxxxxxxx" + error.getMessage());
                }
    
                @Override
                public void onNext(LoginUserBean loginUserBean) {
                    XLog.e("xxxxxxxxxxxx" + loginUserBean.toString());
                }
            });
    
    

    如果注册失败的时候 返回 return Flowable.empty(); 一个空的

    相关文章

      网友评论

      本文标题:Android_MVP小封装

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