presenter 主持人。主导器

======

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

包结构图

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

在splash页面中,判断是否有网络连接,有则跳到下个页面,无则弹出一条消息通知用户,同时在检查网络是否正常的期间显示一个进度条。
 

2. 类目录结构

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

==========

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

==========

android中MVP模式(一) - 清风明月的专栏 - CSDN博客的更多相关文章

  1. mongodb丢失数据的原因剖析 - 迎风飘来的专栏 - CSDN博客 https://blog.csdn.net/yibing548/article/details/50844310

    mongodb丢失数据的原因剖析 - 迎风飘来的专栏 - CSDN博客 https://blog.csdn.net/yibing548/article/details/50844310

  2. Docker安装elasticsearch-head监控ES步骤 - gmijie的专栏 - CSDN博客

    原文:Docker安装elasticsearch-head监控ES步骤 - gmijie的专栏 - CSDN博客 Docker安装elasticsearch-head监控ES步骤 docker拉取镜像 ...

  3. 记一次压测问题定位:connection reset by peer,TCP三次握手后服务端发送RST_网络_c359719435的专栏-CSDN博客 https://blog.csdn.net/c359719435/article/details/80300433

    记一次压测问题定位:connection reset by peer,TCP三次握手后服务端发送RST_网络_c359719435的专栏-CSDN博客 https://blog.csdn.net/c3 ...

  4. 【转】Android Building System 总结 - 一醉千年 - CSDN博客

    原文网址:http://www.360doc.com/content/15/0314/23/1709014_455175716.shtml  Android Building System 总结 收藏 ...

  5. Android中MVP模式与MVC模式比較(含演示样例)

    原文链接 http://sparkyuan.me/ 转载请注明出处 MVP 介绍 MVP模式(Model-View-Presenter)是MVC模式的一个衍生. 主要目的是为了解耦,使项目易于维护. ...

  6. android中MVP模式

    http://blog.csdn.net/ysh06201418/article/details/46534799 Android App整体架构设计的思考   http://blog.csdn.ne ...

  7. 转----------数据库常见笔试面试题 - Hectorhua的专栏 - CSDN博客

    数据库基础(面试常见题) 一.数据库基础 1. 数据抽象:物理抽象.概念抽象.视图级抽象,内模式.模式.外模式 2. SQL语言包括数据定义.数据操纵(Data Manipulation),数据控制( ...

  8. python 使用函数名的字符串调用函数(4种方法)_black-heart的专栏-CSDN博客 https://blog.csdn.net/mrqingyu/article/details/84403924

    funcs = ['fetch_data_' + i for i in ( 'activities', 'banners', 'server_list')]# from operator import ...

  9. Android开发MVP模式解析

    http://www.cnblogs.com/bravestarrhu/archive/2012/05/02/2479461.html 在开发Android应用时,相信很多同学遇到和我一样的情况,虽然 ...

随机推荐

  1. vue-router 编程式导航

    借助vue-router的实例方法,通过编写代码来实现导航的切换: back:回退一步 forward:前进一步 go:指定前进回退步数 push:导航到不同url,向history栈添加一个新的记录 ...

  2. mybatis入门基础----高级映射(一对一,一对多,多对多)

    阅读目录 一:订单商品数据模型 二.一对一查询 三.一对多查询 四.多对多查询 回到顶部 一:订单商品数据模型 1.数据库执行脚本 创建数据库表代码: CREATE TABLE items ( id ...

  3. 原生JS 基础总结

    0. 好习惯 分号 ; 花括号 {}, var 弄清楚 null , undefined 区别 , isNaN, === 与 == 区别 1. prompt , confirm , alert 不同框 ...

  4. myBatis 3.2.7 如何打印 sql

    该文中使用的log框架为logback myBatis3.0.6左右的版本时 打印sql的时候只需要配置如下属性: <logger name="java.sql.Connection& ...

  5. BAT及各大互联网公司2014前端笔试面试题--JavaScript篇(昨天某个群友表示写的简单了点,然后我无情的把他的抄了一遍)

    (某个群友)http://www.cnblogs.com/coco1s/ 很多面试题是我自己面试BAT亲身经历碰到的.整理分享出来希望更多的前端er共同进步吧,不仅适用于求职者,对于巩固复习js更是大 ...

  6. Javascript摸拟自由落体与上抛运动 说明!

    JavaScript 代码 //**************************************** //名称:Javascript摸拟自由落体与上抛运动! //作者:Gloot //邮箱 ...

  7. os_cpu_a.asm

    在OS_CPU_A.ASM中,定义了开.关中断的方法,在uC/OS-II系统中有三种方法可以实现中断开关,而ARM只适用于模式三,即使用一个局部变量,在中断进入之间保存CPU状态,退出时候再恢复状态. ...

  8. 【CTF WEB】函数绕过

    函数绕过 <?php show_source(__FILE__); $c = "<?php exit;?>"; @$c.=$_GET['c']; @$filena ...

  9. Number of Airplanes in the Sky

    Given an interval list which are flying and landing time of the flight. How many airplanes are on th ...

  10. asp.net动态增加服务器端控件并提交表单

    为什么要用原生的呢? 1.目的 原生出现浏览器兼容性问题 极少,不用测试多浏览兼容性 .需要考虑到市面上的其他垃圾浏览器. 2.性能不好 如果不考虑第一条 你可以换一种方式 直接上代码 .aspx页面 ...