zoukankan      html  css  js  c++  java
  • android中MVP模式(一)

    presenter 主持人。主导器

    ======

    1. 明确需求,界面如下:可存,可根据id读取数据。

    包结构图

    2. 建立bean
    [java] view plain copy
     
     print?
    1. public class UserBean {  
    2.      private String mFirstName;  
    3.      private String mLastName;  
    4.   
    5.      public UserBean(String firstName, String lastName) {  
    6.             this. mFirstName = firstName;  
    7.             this. mLastName = lastName;  
    8.      }  
    9.   
    10.      public String getFirstName() {  
    11.             return mFirstName;  
    12.      }  
    13.   
    14.      public String getLastName() {  
    15.             return mLastName;  
    16.      }  
    17. }  
    3. 建立model(处理业务逻辑,这里指数据读写),先写接口,后写实现
    [java] view plain copy
     
     print?
    1. public interface IUserModel {  
    2.      void setID(int id);  
    3.   
    4.      void setFirstName(String firstName);  
    5.   
    6.      void setLastName(String lastName);  
    7.   
    8.      int getID();  
    9.   
    10.      UserBean load(int id);// 通过id读取user信息,返回一个UserBean  
    11. }  
    实现不在这里写了。
    4. 建立view(更新ui中的view状态),这里列出需要操作当前view的方法,也是接口
    [java] view plain copy
     
     print?
    1. public interface IUserView {  
    2.      int getID();  
    3.   
    4.      String getFristName();  
    5.   
    6.      String getLastName();  
    7.   
    8.      void setFirstName(String firstName);  
    9.   
    10.      void setLastName(String lastName);  
    11. }  
    5. 建立presenter(主导器,通过iView和iModel接口操作model和view),activity可以把所有逻辑给presenter处理,这样java逻辑就从手机的activity中分离出来。
    [java] view plain copy
     
     print?
    1. public class UserPresenter {  
    2.      private IUserView mUserView;  
    3.      private IUserModel mUserModel;  
    4.   
    5.      public UserPresenter(IUserView view) {  
    6.             mUserView = view;  
    7.             mUserModel = new UserModel();  
    8.      }  
    9.   
    10.      public void saveUser( int id, String firstName, String lastName) {  
    11.             mUserModel.setID(id);  
    12.             mUserModel.setFirstName(firstName);  
    13.             mUserModel.setLastName(lastName);  
    14.      }  
    15.   
    16.      public void loadUser( int id) {  
    17.            UserBean user = mUserModel.load(id);  
    18.             mUserView.setFirstName(user.getFirstName()); // 通过调用IUserView的方法来更新显示  
    19.             mUserView.setLastName(user.getLastName());  
    20.      }  
    21. }  
    6. activity中实现iview接口,在其中操作view,实例化一个presenter变量。
    [java] view plain copy
     
     print?
    1. public class MainActivity extends Activity implements OnClickListener,IUserView {  
    2.   
    3.      UserPresenter presenter;  
    4.      EditText id,first,last;  
    5.      @Override  
    6.      protected void onCreate(Bundle savedInstanceState) {  
    7.             super.onCreate(savedInstanceState);  
    8.            setContentView(R.layout. activity_main);  
    9.              
    10.            findViewById(R.id. save).setOnClickListener( this);  
    11.            findViewById(R.id. load).setOnClickListener( this);  
    12.             id = (EditText) findViewById(R.id. id);  
    13.             first = (EditText) findViewById(R.id. first);  
    14.             last = (EditText) findViewById(R.id. last);  
    15.              
    16.             presenter = new UserPresenter( this);  
    17.      }  
    18.   
    19.      @Override  
    20.      public void onClick(View v) {  
    21.             switch (v.getId()) {  
    22.             case R.id. save:  
    23.                  presenter.saveUser(getID(), getFristName(), getLastName());  
    24.                  break;  
    25.             case R.id. load:  
    26.                  presenter.loadUser(getID());  
    27.                  break;  
    28.             default:  
    29.                  break;  
    30.            }  
    31.      }  
    32.   
    33.      @Override  
    34.      public int getID() {  
    35.             return new Integer( id.getText().toString());  
    36.      }  
    37.   
    38.      @Override  
    39.      public String getFristName() {  
    40.             return first.getText().toString();  
    41.      }  
    42.   
    43.      @Override  
    44.      public String getLastName() {  
    45.             return last.getText().toString();  
    46.      }  
    47.   
    48.      @Override  
    49.      public void setFirstName(String firstName) {  
    50.             first.setText(firstName);  
    51.      }  
    52.   
    53.      @Override  
    54.      public void setLastName(String lastName) {  
    55.             last.setText(lastName);  
    56.      }  
    57.   
    58. }  
    7. 所谓的mvp,即是(model-处理业务逻辑(主要是数据读写,或者与后台通信(其实也是读写数据)),view-处理ui控件,presenter-主导器,操作model和view)
    ------------
    1. 需求,这个是《android开发必知的50个诀窍》一书中的mvp章节的需求。
    在splash页面中,判断是否有网络连接,有则跳到下个页面,无则弹出一条消息通知用户,同时在检查网络是否正常的期间显示一个进度条。
     

    2. 类目录结构

    [java] view plain copy
     
     print?
    1. 3. model接口和实现  
    2. public interface INetConnect {  
    3.      boolean isNetConnect( Context context);  
    4. }  
    5. public class NetConnect implements INetConnect {  
    6.   
    7.      @Override  
    8.      public boolean isNetConnect(Context context) {  
    9.             if (context != null) {  
    10.                 ConnectivityManager mConnectivityManager = (ConnectivityManager) context  
    11.                           .getSystemService(Context. CONNECTIVITY_SERVICE);  
    12.                 NetworkInfo mNetworkInfo = mConnectivityManager  
    13.                            .getActiveNetworkInfo();  
    14.                  if (mNetworkInfo != null) {  
    15.                       return mNetworkInfo.isAvailable();  
    16.                 }  
    17.            }  
    18.             return false;  
    19.      }  
    20.   
    21. }  
    22.   
    23. 4. view接口  
    24. public interface ISplashView {  
    25.      void showProcessBar();  
    26.      void hideProcessBar();  
    27.      void showNetError();  
    28.      void startNextActivity();  
    29. }  
    30.   
    31. 5. presenter实现  
    32. public class SplashPresenter {  
    33.      private INetConnect connect;  
    34.      private ISplashView iView;  
    35.        
    36.      public SplashPresenter(ISplashView iView){  
    37.             this. iView = iView;  
    38.             connect = new NetConnect();  
    39.      }  
    40.        
    41.      public void didFinishLoading(Context context){  
    42.             iView.showProcessBar();  
    43.             if( connect.isNetConnect(context)){  
    44.                  iView.startNextActivity();  
    45.            } else{  
    46.                  iView.showNetError();  
    47.            }  
    48.             iView.hideProcessBar();  
    49.      }  
    50. }  
    51.   
    52. 6.activity中代码  
    53. public class MainActivity extends Activity implements ISplashView{  
    54.   
    55.      SplashPresenter presenter;  
    56.      private ProgressDialog progressBar;  
    57.      @Override  
    58.      protected void onCreate(Bundle savedInstanceState) {  
    59.             super.onCreate(savedInstanceState);  
    60.            setContentView(R.layout. activity_main);  
    61.              
    62.             presenter = new SplashPresenter( this);  
    63.      }  
    64.   
    65.      @Override  
    66.      protected void onResume() {  
    67.             super.onResume();  
    68.             presenter.didFinishLoading( this);  
    69.      }  
    70.        
    71.      @Override  
    72.      public void showProcessBar() {  
    73.             if ( progressBar == null) {  
    74.                  progressBar = new ProgressDialog( this);  
    75.                  progressBar.setCancelable( true);  
    76.                  progressBar.setCanceledOnTouchOutside( true);  
    77.                  progressBar.setMessage( "更新数据中,请稍后" );  
    78.            }  
    79.             progressBar.show();  
    80.      }  
    81.   
    82.      @Override  
    83.      public void hideProcessBar() {  
    84.             progressBar.hide();  
    85.      }  
    86.   
    87.      @Override  
    88.      public void showNetError() {  
    89.            Toast. makeText(this, "暂无网络", Toast.LENGTH_SHORT).show();  
    90.      }  
    91.   
    92.      @Override  
    93.      public void startNextActivity() {  
    94.            Toast. makeText(this, "跳到下个activity", Toast.LENGTH_SHORT).show();  
    95.      }  
    96.   

    ==========

    MVP模式简单实例

    一个简单的登录界面(实在想不到别的了╮( ̄▽ ̄")╭),点击LOGIN则进行账号密码验证,点击CLEAR则重置输入。

    项目结构看起来像是这个样子的,MVP的分层还是很清晰的。我的习惯是先按模块分Package,在模块下面再去创建model、view、presenter的子Package,当然也可以用model、view、presenter作为顶级的Package,然后把所有的模块的model、view、presenter类都到这三个顶级Package中,就好像有人喜欢把项目里所有的Activity、Fragment、Adapter都放在一起一样。

    首先来看看LoginActivity

    public class LoginActivity extends ActionBarActivity implements ILoginView, View.OnClickListener {
    
        private EditText editUser;
        private EditText editPass;
        private Button   btnLogin;
        private Button   btnClear;
        ILoginPresenter loginPresenter;
        private ProgressBar progressBar;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //find view
            editUser = (EditText) this.findViewById(R.id.et_login_username);
            editPass = (EditText) this.findViewById(R.id.et_login_password);
            btnLogin = (Button) this.findViewById(R.id.btn_login_login);
            btnClear = (Button) this.findViewById(R.id.btn_login_clear);
            progressBar = (ProgressBar) this.findViewById(R.id.progress_login);
    
            //set listener
            btnLogin.setOnClickListener(this);
            btnClear.setOnClickListener(this);
    
            //init
            loginPresenter = new LoginPresenterCompl(this);
            loginPresenter.setProgressBarVisiblity(View.INVISIBLE);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.btn_login_clear:
                    loginPresenter.clear();
                    break;
                case R.id.btn_login_login:
                    loginPresenter.setProgressBarVisiblity(View.VISIBLE);
                    btnLogin.setEnabled(false);
                    btnClear.setEnabled(false);
                    loginPresenter.doLogin(editUser.getText().toString(), editPass.getText().toString());
                    break;
            }
        }
    
        @Override
        public void onClearText() {
            editUser.setText("");
            editPass.setText("");
        }
    
        @Override
        public void onLoginResult(Boolean result, int code) {
            loginPresenter.setProgressBarVisiblity(View.INVISIBLE);
            btnLogin.setEnabled(true);
            btnClear.setEnabled(true);
            if (result){
                Toast.makeText(this,"Login Success",Toast.LENGTH_SHORT).show();
                startActivity(new Intent(this, HomeActivity.class));
            }
            else
                Toast.makeText(this,"Login Fail, code = " + code,Toast.LENGTH_SHORT).show();
        }
    
    
        @Override
        public void onSetProgressBarVisibility(int visibility) {
            progressBar.setVisibility(visibility);
        }
    }

    从代码可以看出LoginActivity只做了findView以及setListener的工作,而且包含了一个ILoginPresenter,所有业务逻辑都是通过调用ILoginPresenter的具体接口来完成。所以LoginActivity的代码看起来很舒爽,甚至有点愉♂悦呢 (/ω\*)。视力不错的你可能还看到了ILoginView接口的实现,如果不懂为什么要这样写的话,可以先往下看,这里只要记住LoginActivity实现了ILoginView接口

    再来看看ILoginPresenter

    public interface ILoginPresenter {
        void clear();
        void doLogin(String name, String passwd);
        void setProgressBarVisiblity(int visiblity);
    }
    public class LoginPresenterCompl implements ILoginPresenter {
        ILoginView iLoginView;
        IUser user;
        Handler    handler;
    
        public LoginPresenterCompl(ILoginView iLoginView) {
            this.iLoginView = iLoginView;
            initUser();
            handler = new Handler(Looper.getMainLooper());
        }
    
        @Override
        public void clear() {
            iLoginView.onClearText();
        }
    
        @Override
        public void doLogin(String name, String passwd) {
            Boolean isLoginSuccess = true;
            final int code = user.checkUserValidity(name,passwd);
            if (code!=0) isLoginSuccess = false;
            final Boolean result = isLoginSuccess;
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    iLoginView.onLoginResult(result, code);
                }
            }, 3000);
    
        }
    
        @Override
        public void setProgressBarVisiblity(int visiblity){
            iLoginView.onSetProgressBarVisibility(visiblity);
        }
    
        private void initUser(){
            user = new UserModel("mvp","mvp");
        }
    }

    从代码可以看出,LoginPresenterCompl保留了ILoginView的引用,因此在LoginPresenterCompl里就可以直接进行UI操作了,而不用在Activity里完成。这里使用了ILoginView引用,而不是直接使用Activity,这样一来,如果在别的Activity里也需要用到相同的业务逻辑,就可以直接复用LoginPresenterCompl类了(一个Activity可以包含一个以上的Presenter,总之,需要什么业务就new什么样的Presenter,是不是很灵活(@ ̄︶ ̄@)),这也是MVP的核心思想

    通过IVIew和IPresenter,把Activity的UI LogicBusiness Logic分离开来,Activity just does its basic job! 至于Model嘛,还是原来MVC里的Model。

    再来看看ILoginView,至于ILoginView的实现类呢,翻到上面看看LoginActivity吧

    public interface ILoginView {
        public void onClearText();
        public void onLoginResult(Boolean result, int code);
        public void onSetProgressBarVisibility(int visibility);
    }

    代码这种东西放在日志里讲好像除了把整个版面拉长没什么卵用,我把几种自己常用的MVP的写法写成一个Demo项目,欢迎围观和PullRequest:Android-MVP-Pattern

    ==========

  • 相关阅读:
    【小贴士】zepto find元素以及ios弹出键盘可能让你很头疼
    【iScroll源码学习04】分离IScroll核心
    【iScroll源码学习03】iScroll事件机制与滚动条的实现
    展望14,献给困惑的初级前端,理想不甘消磨,目标不能停滞!
    【iScroll源码学习02】分解iScroll三个核心事件点
    原生andriod浏览器回退后dom(click)事件全体失效问题探究
    【iScroll源码学习01】准备阶段
    【iScroll源码学习00】模拟iScroll
    【再探backbone 03】博客园单页应用实例(提供源码)
    【再探backbone 02】集合-Collection
  • 原文地址:https://www.cnblogs.com/yue31313/p/7488801.html
Copyright © 2011-2022 走看看