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. harbor高可用集群配置

    目录 说明 双主复制 主从同步 双主复制说明 多harbor实例共享后端存储 方案说明 环境说明 配置说明 安装redis和mysql 导入registry数据库 配置harbor 挂载nfs目录 修 ...

  2. cookie添加删除修改

    //cookie添加 document.cookie="username=John Doe"; //添加过期时间 document.cookie="username1=J ...

  3. JXL读取,写入Excel

    JXL读取,写入Excel2003 相关阅读:poi 读写excel2003:http://www.cnblogs.com/gavinYang/p/3576739.htmlpoi 读写excel200 ...

  4. 比特币全节点(bitcoind) eth 全节点

    运行全节点的用途:  1.挖矿  2.钱包   运行全节点,可以做关于btc的任何事情,例如创建钱包地址.管理钱包地址.发送交易.查询全网的交易信息等等 选个节点钱包:bitcoind 1.配置文件: ...

  5. 翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化

    翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化 翻译自: Exploring GLSL – Normal Visualizer with Geometry Shaders (Shader ...

  6. ASP.Net巧用窗体母版页

    背景:每个网页的基本框架结构类似: 浏览网站的时候会发现,好多网站中,每个网页的基本框架都是一样的,比如,最上面都是网站的标题,中间是内容,最下面是网站的版权.开发提供商等信息: 在这些网页中,表头. ...

  7. 20155238 2016-2017-2 《Java程序设计》第五周学习总结

    教材学习内容总结 Java语言中所有的错误都会包装为对象.使用try.catch可以对对象做处理. 设计错误对象都继承自java.lang.Throwable类.Throwable定义了取得错误信息, ...

  8. 第12月第29天 cocos quick manual

    1. Example: $ cd cocos2d-x $ ./setup.py $ source FILE_TO_SAVE_SYSTEM_VARIABLE $ cocos new MyGame -p ...

  9. parallelogram

    The parallelogram law in inner product spaces Vectors involved in the parallelogram law. In a normed ...

  10. Implement Queue by Two Stacks & Implement Stack using Queues

    Implement Queue by Two Stacks Implement the following operations of a queue using stacks. push(x) -- ...