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. 鸟哥的Linux私房菜——第十七章:Linux 账号与身份管理

    视频链接:http://www.bilibili.com/video/av10669732/ 1. Linux 的账号与群组1.1 使用者识别: UID 与 GID1.2 使用者账号:/etc/pas ...

  2. java8 使用 lamda 表达式 完成 map reduce

    java8支持了函数编程,可以让java代码更简洁和易读. 传统 for 循环方式: List<String> list = Arrays.asList("C",&qu ...

  3. node.js通过edge访问.net动态链接库

    从了解node.js到现在经历了几个月时间,一直忙于实际的项目,没有动手写点关于node.js的代码.最近将开发工作安排就绪,个人的时间相对从容了,所以这几天开始测试一下node.js. 多年来,一直 ...

  4. nodejs npm install -g 全局安装

    1. npm install xxx -g 时, 模块将被下载安装到[全局目录]中. [全局目录]通过 npm config set prefix "目录路径" 来设置. 比如说, ...

  5. BSGS 算法

    求解 A^x ≡ B mod C  C是质数 的最小非负整数解 证明:A^x ≡ A^(x%φ(C)) mod C A^(x%φ(C))  ≡ A^(x-k*φ(C)) ≡ (A^x)/ A^(k*φ ...

  6. Codeforces 238 div2 B. Domino Effect

    题目链接:http://codeforces.com/contest/405/problem/B 解题报告:一排n个的多米诺骨牌,规定,若从一边推的话多米诺骨牌会一直倒,但是如果从两个方向同时往中间推 ...

  7. 机器学习&深度学习视频资料汇总

      第一部分 基础语言   pandax视频教程 链接: https://pan.baidu.com/s/1pLqavVX 密码: fath python入门到精通 链接: https://pan.b ...

  8. E. Andrew and Taxi(二分+拓扑判环)

    题目链接:http://codeforces.com/contest/1100/problem/E 题目大意:给你n和m,n代表有n个城市,m代表有m条边,然后m行输入三个数,起点,终点,花费.,每一 ...

  9. Redis知识点总结

    1.单线程 单线程模型来处理客户端的请求,对读写等事件的相应是通过对epoll函数的包装来做到的,Redis的实际处理速度完全依靠主线程的执行效率. Epoll是Linux内核为处理大批量文件描述符而 ...

  10. 使用SpringCloud搭建高可用服务注册中心

    我们需要的,不仅仅是一个服务注册中心而已,而是一个高可用服务注册中心. 上篇博客中我们介绍了如何使用Spring Cloud搭建一个服务注册中心,但是搭建好的服务注册中心是一个单节点的服务注册中心,这 ...