MVP架构

作者: 玄策 | 来源:发表于2018-02-24 11:00 被阅读24次

    目录

    1)MVP简介
    2)MVP实例


    1)MVP简介

    MVP模式将Activity中的业务逻辑全部剥离出来,Activity只做UI部分的处理,所有业务逻辑层由Presenter层去处理。

    分层 说明
    View Activity,Fragment,负责处理UI
    Presenter 业务逻辑层,既能调用UI,又能请求数据源
    Model 纯业务数据源的接口与实现

    M层与V层无法直接通信,需要通过P层处理。

    MVP

    2)MVP实例

    实现一个登录请求

    假设我们来实现一个登录请求。


    工程结构

    -定义实体Bean

    实体Bean
    public class LoginReq {
        private String username;
        private String password;
        ...
    }
    
    public class LoginResponse {
        private String retcode;
        private String retinfo;
        private UserData userData;
        ...
    }
    public class UserData {
        private String name;
        private String age;
        ...
    }
    

    -Model层

    Model层
    • Callback接口, 是Model给Presenter反馈数据信息的载体,需要在Callback中定义数据的各种反馈状态
    //通过泛型T表示接受任意类型
    public interface MvpCallback<T> {
        /**
         * 数据请求成功
         * @param data 请求到的数据
         */
        void onSuccess(T data);
    
        /**
         *  使用网络API接口请求方式时,虽然已经请求成功但是由
         *  于{@code msg}的原因无法正常返回数据。
         */
        void onFail(T data);
    
        /**
         * 请求数据失败,指在请求网络API接口请求方式时,出现无法联网、
         * 缺少权限,内存泄露等原因导致无法连接到请求数据源。
         */
        void onError();
    
        /**
         * 当请求数据结束时,无论请求结果是成功,失败或是抛出异常都会执行此方法给用户做处理,通常做网络
         * 请求时可以在此处隐藏“正在加载”的等待控件
         */
        void onComplete();
    }
    
    • 登录业务接口,这里采用了ARouter-IProvider的服务依赖注入的方式去解耦服务,如不需要可不用继承IProvider
    public interface ILoginBiz extends IProvider {
    
        //登录操作
        void login(LoginReq req, MvpCallback mvpCallback);
    
        //存储登录信息
        void saveUserdata(UserData userdata);
    }
    
    • 登录业务实现,
    @Route(path = "/service/login", name="登录服务")
    public class LoginBiz implements ILoginBiz {
    
        @Override
        public void login(LoginReq req, final MvpCallback mvpCallback) {
            Map<String,String> param = new HashMap<String, String>();
            //调用公共组件库的OkHttpUtil进行网络API请求
            OkHttpUtil.sendRequestPost(param, new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    //模拟2秒休眠
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //回调onComplete
                    mvpCallback.onComplete();
                    //模拟response数据
                    UserData userData = new UserData("涂高峰","18");
                    LoginResponse loginResponse = new LoginResponse("000000","登录成功",userData);
                    //回调onSuccess
                    mvpCallback.onSuccess(loginResponse.getUserData());
                }
            });
        }
    
        @Override
        public void saveUserdata(UserData userdata) {
    
        }
    
        @Override
        public void init(Context context) {
        }
    }
    

    -View层,View接口是Activity层和Presenter层的中间层,它用于根据具体业务需要,为Presenter层提供调用Activity中具体UI操作的方法。

    View层
    • IMvpView,抽象出的公共View
    public interface IMvpView {
    
        /**
         * 显示正在加载view
         */
        void showLoading();
    
        /**
         * 关闭正在加载view
         */
        void hideLoading();
    
        /**
         * 显示提示
         * @param msg
         */
        void showToast(String msg);
    }
    
    • ILoginView,登录业务View,继承了IMvpView。
    public interface ILoginView extends IMvpView {
    
        /**
         * 登录请求成功提示
         */
        void loginSuccess(UserData userData);
    
        /**
         * 登录请求失败提示
         */
        void loginFail(String text);
    }
    

    -Presenter层,具体的业务逻辑处理Java类,不含任何Android-API操作,负责请求数据源,并对数据源反馈做处理。

    Presenter层
    • MvpPresenter,抽象出公共的Presenter,
    public class MvpPresenter<V extends IMvpView> {
    
        /**
         * 绑定的view
         */
        private V mvpView;
    
        /**
         * 绑定view,一般在初始化中调用该方法
         */
        public void attachView(V view){
            this.mvpView = view;
        }
    
        /**
         * 断开view,一般在onDestroy中调用
         * 对于Activity异常销毁导致mvpView空指针
         * 采用attachView和detachView,将view与activity生命周期绑定
         */
        public void detachView(){
            this.mvpView = null;
        }
    
        /**
         * 是否与View建立连接
         * 每次调用业务请求的时候都要出先调用方法检查是否与View建立连接
         */
        public boolean isViewAttached(){
            return this.mvpView != null;
        }
    
        /**
         * 获取连接的view
         */
        public V getView(){
            return this.mvpView;
        }
    
        /**
         * 获取连接的view名称
         */
        public String getViewName(){
            return this.mvpView.getClass().getSimpleName();
        }
    }
    
    • LoginPresenter,登录业务Presenter,继承了MvpPresenter。
    public class LoginPresenter extends MvpPresenter<ILoginView> {
        //依赖注入发现服务
        @Autowired(name = "/service/login")
        LoginBiz loginBiz;
    
        public LoginPresenter() {
    //        this.loginBiz = new LoginBiz();
            //依赖注入
            ARouter.getInstance().inject(this);
        }
    
        public void login(LoginReq req){
    
            if (!isViewAttached()){
                //如果没有View引用就不加载数据
                return;
            }
    
            getView().showLoading();
    
            loginBiz.login(req, new MvpCallback() {
                @Override
                public void onSuccess(final Object data) {
                    if (isViewAttached()){
                        MainLooper.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                getView().loginSuccess((UserData) data);
                            }
                        });
                    }
                }
    
                @Override
                public void onFail(Object data) {
    
                }
    
                @Override
                public void onError() {
    
                }
    
                @Override
                public void onComplete() {
                    if (isViewAttached()){
                        MainLooper.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                getView().hideLoading();
                            }
                        });
                    }
                }
            });
        }
    }
    

    -Activity,登录业务Activity,实现了ILoginView

    public class MainActivity extends AppCompatActivity implements ILoginView,View.OnClickListener{
    
        private LoginPresenter loginPresenter;
        private TextView txt;
        private ProgressBar progressBar;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            txt = findViewById(R.id.txt);
            progressBar = findViewById(R.id.progressBar);
            findViewById(R.id.success_btn).setOnClickListener(this);
    
            //初始化Presenter
            loginPresenter = new LoginPresenter();
            //绑定View引用
            loginPresenter.attachView(this);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            //断开View引用
            loginPresenter.detachView();
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.success_btn:
                    LoginReq loginReq = new LoginReq("tgf","123");
                    loginPresenter.login(loginReq);
                    break;
            }
        }
    
        @Override
        public void showLoading() {
            progressBar.setVisibility(View.VISIBLE);
        }
    
        @Override
        public void hideLoading() {
            progressBar.setVisibility(View.GONE);
        }
    
        @Override
        public void showToast(String msg) {
            Toast.makeText(this,msg,Toast.LENGTH_SHORT).show();
        }
    
        @Override
        public void loginSuccess(UserData userData) {
            txt.setText("姓名: "+userData.getName() + "年龄"+ userData.getAge());
        }
    
        @Override
        public void loginFail(String text) {
        }
    }
    

    -其他工具类

    public class MainLooper extends Handler {
        private static MainLooper instance = new MainLooper(Looper.getMainLooper());
    
        protected MainLooper(Looper looper) {
            super(looper);
        }
    
        public static MainLooper getInstance() {
            return instance;
        }
    
        public static void runOnUiThread(Runnable runnable) {
            if(Looper.getMainLooper().equals(Looper.myLooper())) {
                runnable.run();
            } else {
                instance.post(runnable);
            }
        }
    }
    

    参考资料

    谷歌官方架构蓝图Android Architecture Blueprints
    Android MVP架构搭建

    相关文章

      网友评论

          本文标题:MVP架构

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