zoukankan      html  css  js  c++  java
  • MVP模式 详解 案例


    介绍
    MVC:
    • View:对应于布局文件
    • Model:业务逻辑和实体模型
    • Controllor:对应于Activity
    实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,造成了Activity既像View又像Controller

    程序员对于MVP的普遍的认识是:代码很清晰,不过增加了很多类
    当将架构改为MVP以后,Presenter的出现,将Actvity视为View层,Presenter负责完成View层与Model层的交互。现在是这样的:
    • View 对应于Activity,负责View的绘制以及与用户交互
    • Model 依然是业务逻辑和实体模型
    • Presenter 负责完成View和Model间的交互
    从并不标准的MVC到MVP的一个转变,减少了Activity的职责,简化了Activity中的代码,将复杂的逻辑代码提取到了Presenter中进行处理
    与之对应的好处就是,耦合度更低,更方便的进行测试。

    MVC与MVP的一个区别示意图:

    其实最明显的区别就是,MVC中是允许Model和View进行交互的,而MVP中很明显,Model与View之间的交互由Presenter完成
    还有一点就是Presenter与View之间的交互是通过接口的。

    案例


    Activity包(view包)
    /**
     * 梳理此Activity所有需要的方法,将这些方法全部封装到一个接口中
     * @author 白乾涛
     */
    public interface IUserLoginView {
        public String getUserName();
        public String getPassword();
        public void clearUserName();
        public void clearPassword();
        public void toMainActivity(User user);
        public void showFailedError();
        public void showLoading();
        public void hideLoading();
    }

    /**
     * 简单来说,对Activity的所有操作(方法)都被剖离在了两个地方,一个是在IUserLoginView中,这里面都是对Activity的一些最基本的操作
     * 另一个在Presenter中,比较复杂的【业务逻辑】都会放在这里(目的当然是减少Activity的代码逻辑)
     * 一定要明白,之所以将Activity中的这些方法剖离在IUserLoginView中,是为了在Presenter中能通过操作IUserLoginView来操作Activity(扩展性)
     * 
     * @author 白乾涛
     */
    public class UserLoginActivity extends Activity implements IUserLoginView, OnClickListener {
        private EditText id_et_username;
        private EditText id_et_password;
        private Button id_btn_login;
        private Button id_btn_clear;
        private UserLoginPresenter mUserLoginPrestener = new UserLoginPresenter(this);//这里是将IUserLoginView接口的实例(即Activity)传给了Presenter
        private ProgressBar id_progressbar;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_user_login);
            id_et_username = (EditText) findViewById(R.id.id_et_username);
            id_et_password = (EditText) findViewById(R.id.id_et_password);
            id_btn_login = (Button) findViewById(R.id.id_btn_login);
            id_btn_clear = (Button) findViewById(R.id.id_btn_clear);
            id_progressbar = (ProgressBar) findViewById(R.id.id_progressbar);
            id_btn_login.setOnClickListener(this);
            id_btn_clear.setOnClickListener(this);
        }
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.id_btn_login:
                //这里面的两个方法在Presenter中,当我们需要修改业务逻辑时,只需修改Prestener类中的相应方法即可!
                mUserLoginPrestener.login();
                break;
            case R.id.id_btn_clear:
                mUserLoginPrestener.clear();
                break;
            }
        }
        //******************************************************************************************
        @Override
        public String getUserName() {
            return id_et_username.getText().toString();
        }
        @Override
        public String getPassword() {
            return id_et_password.getText().toString();
        }
        @Override
        public void clearUserName() {
            id_et_username.setText("");
        }
        @Override
        public void clearPassword() {
            id_et_password.setText("");
        }
        @Override
        public void toMainActivity(User user) {
            Toast.makeText(getApplicationContext(), user.getUsername() + "--登录成功", Toast.LENGTH_SHORT).show();
        }
        @Override
        public void showFailedError() {
            Toast.makeText(getApplicationContext()"登录失败", Toast.LENGTH_SHORT).show();
        }
        @Override
        public void showLoading() {
            id_progressbar.setVisibility(View.VISIBLE);
        }
        @Override
        public void hideLoading() {
            id_progressbar.setVisibility(View.INVISIBLE);
        }
    }

    presenter包
    /**
     * 这就是传说中的Prestener,这里面封装的都是Activity中复杂的业务逻辑
     * @author 白乾涛
     */
    public class UserLoginPresenter {
        private IUserBiz userBiz;
        private IUserLoginView userLoginView;
        private Handler mHandler = new Handler() {
            public void handleMessage(android.os.Message msg) {
            };
        };
        //在构造Prestener时,需要传递一个IUserLoginView接口的实例(其实就是Activity),只有这样,Prestener才能对此实例进行操作
        public UserLoginPresenter(IUserLoginView userLoginView) {
            this.userBiz = new UserBiz();
            this.userLoginView = userLoginView;
        }
        public void login() {
            userLoginView.showLoading();
            //为了更具扩展性及进一步解耦,具体的登录逻辑又通过同样的方式转移到了IUserBiz接口上(统一放在biz包下)
            userBiz.login(userLoginView.getUserName()userLoginView.getPassword()new OnLoginListener() {
                @Override
                public void loginSuccess(final User user) {
                    //需要再UI线程执行
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            userLoginView.toMainActivity(user);
                            userLoginView.hideLoading();
                        }
                    });
                }
                @Override
                public void loginFailed() {
                    //需要在UI线程执行
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            userLoginView.showFailedError();
                            userLoginView.hideLoading();
                        }
                    });
                }
            });
        }
        public void clear() {
            userLoginView.clearPassword();
            userLoginView.clearUserName();
        }
    }

    bean包
    /**
     * 一个业务bean,所有需要被操作的基本元素(不包括View)都应该定义在这里
     * @author 白乾涛
     */
    public class User {
        private String username;
        private String password;
        public String getUsername() {
            return username;
        }
        public String getPassword() {
            return password;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    }

    biz(业务)包
    /**
     * 复杂的业务逻辑在这里定义:如,登录、忘记密码、联系客服
     * @author 白乾涛
     */
    public interface IUserBiz {
        public void login(String username, String password, OnLoginListener onLoginListener);
    }

    /**
     * 复杂业务逻辑的具体实现:如具体的登录代码在这里编写
     * 这里面有一个回调
     * @author 白乾涛
     */
    public class UserBiz implements IUserBiz {
        @Override
        public void login(final String username, final String password, final OnLoginListener onLoginListener) {
            new Thread() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if ("username".equals(username) && "password".equals(password)) {
                        User user = new User();
                        user.setUsername(username);
                        user.setPassword(password);
                        //成功时的回调
                        onLoginListener.loginSuccess(user);
                    } else {
                        //失败时的回调
                        onLoginListener.loginFailed();
                    }
                }
            }.start();
        }
    }

    /**
     * 这个其实不算是MVP中的东西(但一般都会有),这是一个回调,当执行复杂逻辑的同时做一些回调处理
     * @author 白乾涛
     */
    public interface OnLoginListener {
        public void loginSuccess(User user);
        public void loginFailed();
    }





  • 相关阅读:
    学习MongoDB(Troubleshoot Replica Sets) 集群排除故障
    MyBatis 相同事物查询缓存问题
    Spring事物源码
    Spring Session Redis
    Tomcat配置多个域名绑定到不同项目
    Shiro相关文章资料
    一网打尽:Java 程序员必须了解的计算机底层知识!
    Chrome 80 调教篇
    谭浩强《C++程序设计》
    HTTP/HTTPS协议
  • 原文地址:https://www.cnblogs.com/baiqiantao/p/5840400.html
Copyright © 2011-2022 走看看