Android进阶-MVP

一、什么是MVP?

MVP (Model View Presenter)模式由MVP模式演变而来,它将View层和逻辑层分离。

二、为什么使用MVP?

将View层和逻辑层分离后有利于拓展,比如当前代码属于来自本地数据库,如果需求变更数据来自网络,我们就不必重写整个View层。通过MVP我们将大部分逻辑抽出Activity,写在Presenter层。分层后就可以各司其职,也方便测试。

三、各层的职责。

  1. Presenter的职责:从Modle层获取数据经过处理后交给View层展示。
  2. View的职责:MVP将Activity划在View层,Activity引用Presenter。View层主要有两个任务。1.对外提供修改控件属性的接口。2.响应外部事件,交给Presenter处理。这样Activity的任务就很明确了。
  3. Model的职责:提供给Presenter需要的数据。

四、实例.

一个登陆的例子(项目代码在这里下载:https://github.com/gatsbydhn/androidmvp):

View层:

View接口,Activity实现了该接口,方便以后拓展:

 1 public interface LoginView {
 2     void showProgress();
 3
 4     void hideProgress();
 5
 6     void setUsernameError();
 7
 8     void setPasswordError();
 9
10     void navigateToHome();
11 }

Activity:

 1 public class LoginActivity extends Activity implements LoginView, View.OnClickListener {
 2
 3     private ProgressBar progressBar;
 4     private EditText username;
 5     private EditText password;
 6     private LoginPresenter presenter;
 7
 8     @Override
 9     protected void onCreate(Bundle savedInstanceState) {
10         super.onCreate(savedInstanceState);
11         setContentView(R.layout.activity_login);
12
13         progressBar = (ProgressBar) findViewById(R.id.progress);
14         username = (EditText) findViewById(R.id.username);
15         password = (EditText) findViewById(R.id.password);
16         findViewById(R.id.button).setOnClickListener(this);
17
18         presenter = new LoginPresenterImpl(this);
19     }
20
21     @Override protected void onDestroy() {
22         presenter.onDestroy();
23         super.onDestroy();
24     }
25
26     @Override public void showProgress() {
27         progressBar.setVisibility(View.VISIBLE);
28     }
29
30     @Override public void hideProgress() {
31         progressBar.setVisibility(View.GONE);
32     }
33
34     @Override public void setUsernameError() {
35         username.setError(getString(R.string.username_error));
36     }
37
38     @Override public void setPasswordError() {
39         password.setError(getString(R.string.password_error));
40     }
41
42     @Override public void navigateToHome() {
43         startActivity(new Intent(this, MainActivity.class));
44         finish();
45     }
46
47     @Override public void onClick(View v) {
48         presenter.validateCredentials(username.getText().toString(), password.getText().toString());
49     }
50 }

分析:如前面所说Activilty里面的方法分为两类:1.修改控件属性如showProgress(),hideProgress()等,这些接口将被Presenter调用。2.响应外部事件比如onClick(),onDestroy()等,调用Presenter来完成具体的任务。

下面是Presenter层:

接口,方便拓展:

1 public interface LoginPresenter {
2     void validateCredentials(String username, String password);
3
4     void onDestroy();
5 }

实现类:

 1 public class LoginPresenterImpl implements LoginPresenter, LoginInteractor.OnLoginFinishedListener {
 2
 3     private LoginView loginView;
 4     private LoginInteractor loginInteractor;
 5
 6     public LoginPresenterImpl(LoginView loginView) {
 7         this.loginView = loginView;
 8         this.loginInteractor = new LoginInteractorImpl();
 9     }
10
11     @Override public void validateCredentials(String username, String password) {
12         if (loginView != null) {
13             loginView.showProgress();
14         }
15
16         loginInteractor.login(username, password, this);
17     }
18
19     @Override public void onDestroy() {
20         loginView = null;
21     }
22
23     @Override public void onUsernameError() {
24         if (loginView != null) {
25             loginView.setUsernameError();
26             loginView.hideProgress();
27         }
28     }
29
30     @Override public void onPasswordError() {
31         if (loginView != null) {
32             loginView.setPasswordError();
33             loginView.hideProgress();
34         }
35     }
36
37     @Override public void onSuccess() {
38         if (loginView != null) {
39             loginView.navigateToHome();
40         }
41     }
42 }

分析:这里使用面向接口编程,方便以后拓展。Presenter引用Model层的LoginInteractor,完成View交给的任务validateCredentials(),该方法中调用LoginInteractor获取登陆数据。

Model层:

接口:

 1 public interface LoginInteractor {
 2
 3     interface OnLoginFinishedListener {
 4         void onUsernameError();
 5
 6         void onPasswordError();
 7
 8         void onSuccess();
 9     }
10
11     void login(String username, String password, OnLoginFinishedListener listener);
12
13 }

实现类:

 1 public class LoginInteractorImpl implements LoginInteractor {
 2
 3     @Override
 4     public void login(final String username, final String password, final OnLoginFinishedListener listener) {
 5         // Mock login. I‘m creating a handler to delay the answer a couple of seconds
 6         new Handler().postDelayed(new Runnable() {
 7             @Override public void run() {
 8                 boolean error = false;
 9                 if (TextUtils.isEmpty(username)){
10                     listener.onUsernameError();
11                     error = true;
12                 }
13                 if (TextUtils.isEmpty(password)){
14                     listener.onPasswordError();
15                     error = true;
16                 }
17                 if (!error){
18                     listener.onSuccess();
19                 }
20             }
21         }, 2000);
22     }
23 }

分析:登陆应该要从数据库获取数据验证账号密码是否正确,这里省略了这一步骤,但是要明白,这一层的职责是提供数据,不管是从数据库还是网络。

时间: 2024-10-13 08:17:08

Android进阶-MVP的相关文章

我的Android进阶之旅------>Java字符串格式化方法String.format()格式化float型时小数点变成逗号问题

今天接到一个波兰的客户说有个APP在英文状态下一切运行正常,但是当系统语言切换到波兰语言的时候,程序奔溃了.好吧,又是我来维护. 好吧,先把系统语言切换到波兰语,切换到波兰语的方法查看文章 我的Android进阶之旅------>Android[设置]-[语言和输入法]-[语言]列表中找到相应语言所对应的列表项 地址:http://blog.csdn.net/ouyang_peng/article/details/50209789 ================================

【Android进阶】解析XML文件之使用DOM解析器

在前面的文章中,介绍了使用SAX解析器对XML文件进行解析,SAX解析器的优点就是占用内存小.这篇文章主要介绍使用DOM解析器对XML文件进行解析.DOM解析器的优点可能是理解起来比较的直观,当然,每个人对不同的解析方法可能有不同的喜好.但是DOM解析器有个比较大的缺点,就是占用内存比较多,在Android中的XML解析中,还是更推荐其他的解析方式. 下面介绍使用DOM解析器对XML进行解析. 下面是我们需要解析的xml文件 <?xml version="1.0" encodin

Android进阶——Preference详解之Preference系的基本应用(三)

引言 前面一篇文章Android进阶--Preference详解之Preference系的基本应用和管理(二)介绍了二级Preference的使用和特点,接下来进入系统给我提供的底级Preference的使用CheckBox选择项CheckBoxPreference.EditText编辑对话框EditTextPreference.列表选择ListPreference.多项选择MultiSelectListPreference. 开关选择SwitchPreference的应用和管理.以期大家能在学

Android进阶2之PopupWindow弹窗(有点悬浮窗的感觉)

PopupWindow是一个可以用来显示一个任意的视图的弹出窗口,他需要完全依赖layout布局. 它没什么界面,在弹出的窗口中完全显示布局中的控件. 上面两个美女头就是弹窗PopupWindow显示的内容.是两个Button. 具体实现: 注意:那三个Button不能和普通的Button一样通过findViewById()方法获得,必须首先说的Button所在的视图,View popview = layoutInflater.inflate(R.layout.poplayout, null);

Android 进阶学习:事件分发机制全然解析,带你从源代码的角度彻底理解(上)

http://blog.csdn.net/guolin_blog/article/details/9097463 事实上我一直准备写一篇关于Android事件分发机制的文章,从我的第一篇博客開始,就零零散散在好多地方使用到了Android事件分发的知识.也有好多朋友问过我各种问题,比方:onTouch和onTouchEvent有什么差别,又该怎样使用?为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?为什么图片轮播器里的图片使用Button而不用ImageView?

【Android进阶】Junit单元测试环境搭建以及简单实用

单元测试的目的 首先,Junit单元测试要实现的功能,就是用来测试写好的方法是否能够正确的执行,一般多用于对业务方法的测试. 单元测试的环境配置 1.在AndroidManifest清单文件的Application节点下,引入单元测试使用的库 2.在AndroidManifest清单文件与Application节点平行的节点中,添加instrumentation节点 下面是一个完整的配置的代码 <manifest xmlns:android="http://schemas.android.

【Android进阶】Android面试题目整理与讲解

这一篇文章专门整理一下研究过的Android面试题,内容会随着学习不断的增加,如果答案有错误,希望大家可以指正 1.简述Activity的生命周期 当Activity开始启动的时候,首先调用onCreate(),onStart(),onResume()方法,此时Activity对用户来说,是可见的状态 当Activity从可见状态变为被Dialog遮挡的状态的时候,会调用onPause()方法,此时的Activity对用户可见,但是不能相 应用户的点击事件 当Activity从可见状态变为被其他

我的Android进阶之旅------&gt;如何获取系统中定义了那些权限

在Window控制台中输入如下命令可以看到Android系统中列出的所有权限(如果自定义权限注册成功,在这里也会找到这些自定义的权限) adb shell pm list permissions C:\Users\Administrator>adb shell pm list permissions All Permissions: permission:android.permission.INTERNAL_SYSTEM_WINDOW permission:android.permission

我的Android进阶之旅------&gt;Android疯狂连连看游戏的实现之实现游戏逻辑(五)

在上一篇<我的Android进阶之旅------>Android疯狂连连看游戏的实现之加载界面图片和实现游戏Activity(四)>中提到的两个类: GameConf:负责管理游戏的初始化设置信息. GameService:负责游戏的逻辑实现. 其中GameConf的代码如下:cn\oyp\link\utils\GameConf.java package cn.oyp.link.utils; import android.content.Context; /** * 保存游戏配置的对象