android中MVP模式(一) - 清风明月的专栏 - CSDN博客
presenter 主持人。主导器
======
1. 明确需求,界面如下:可存,可根据id读取数据。
- public class UserBean {
- private String mFirstName;
- private String mLastName;
- public UserBean(String firstName, String lastName) {
- this. mFirstName = firstName;
- this. mLastName = lastName;
- }
- public String getFirstName() {
- return mFirstName;
- }
- public String getLastName() {
- return mLastName;
- }
- }
- public interface IUserModel {
- void setID(int id);
- void setFirstName(String firstName);
- void setLastName(String lastName);
- int getID();
- UserBean load(int id);// 通过id读取user信息,返回一个UserBean
- }
- public interface IUserView {
- int getID();
- String getFristName();
- String getLastName();
- void setFirstName(String firstName);
- void setLastName(String lastName);
- }
- public class UserPresenter {
- private IUserView mUserView;
- private IUserModel mUserModel;
- public UserPresenter(IUserView view) {
- mUserView = view;
- mUserModel = new UserModel();
- }
- public void saveUser( int id, String firstName, String lastName) {
- mUserModel.setID(id);
- mUserModel.setFirstName(firstName);
- mUserModel.setLastName(lastName);
- }
- public void loadUser( int id) {
- UserBean user = mUserModel.load(id);
- mUserView.setFirstName(user.getFirstName()); // 通过调用IUserView的方法来更新显示
- mUserView.setLastName(user.getLastName());
- }
- }
- public class MainActivity extends Activity implements OnClickListener,IUserView {
- UserPresenter presenter;
- EditText id,first,last;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout. activity_main);
- findViewById(R.id. save).setOnClickListener( this);
- findViewById(R.id. load).setOnClickListener( this);
- id = (EditText) findViewById(R.id. id);
- first = (EditText) findViewById(R.id. first);
- last = (EditText) findViewById(R.id. last);
- presenter = new UserPresenter( this);
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id. save:
- presenter.saveUser(getID(), getFristName(), getLastName());
- break;
- case R.id. load:
- presenter.loadUser(getID());
- break;
- default:
- break;
- }
- }
- @Override
- public int getID() {
- return new Integer( id.getText().toString());
- }
- @Override
- public String getFristName() {
- return first.getText().toString();
- }
- @Override
- public String getLastName() {
- return last.getText().toString();
- }
- @Override
- public void setFirstName(String firstName) {
- first.setText(firstName);
- }
- @Override
- public void setLastName(String lastName) {
- last.setText(lastName);
- }
- }
2. 类目录结构
- 3. model接口和实现
- public interface INetConnect {
- boolean isNetConnect( Context context);
- }
- public class NetConnect implements INetConnect {
- @Override
- public boolean isNetConnect(Context context) {
- if (context != null) {
- ConnectivityManager mConnectivityManager = (ConnectivityManager) context
- .getSystemService(Context. CONNECTIVITY_SERVICE);
- NetworkInfo mNetworkInfo = mConnectivityManager
- .getActiveNetworkInfo();
- if (mNetworkInfo != null) {
- return mNetworkInfo.isAvailable();
- }
- }
- return false;
- }
- }
- 4. view接口
- public interface ISplashView {
- void showProcessBar();
- void hideProcessBar();
- void showNetError();
- void startNextActivity();
- }
- 5. presenter实现
- public class SplashPresenter {
- private INetConnect connect;
- private ISplashView iView;
- public SplashPresenter(ISplashView iView){
- this. iView = iView;
- connect = new NetConnect();
- }
- public void didFinishLoading(Context context){
- iView.showProcessBar();
- if( connect.isNetConnect(context)){
- iView.startNextActivity();
- } else{
- iView.showNetError();
- }
- iView.hideProcessBar();
- }
- }
- 6.activity中代码
- public class MainActivity extends Activity implements ISplashView{
- SplashPresenter presenter;
- private ProgressDialog progressBar;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout. activity_main);
- presenter = new SplashPresenter( this);
- }
- @Override
- protected void onResume() {
- super.onResume();
- presenter.didFinishLoading( this);
- }
- @Override
- public void showProcessBar() {
- if ( progressBar == null) {
- progressBar = new ProgressDialog( this);
- progressBar.setCancelable( true);
- progressBar.setCanceledOnTouchOutside( true);
- progressBar.setMessage( "更新数据中,请稍后" );
- }
- progressBar.show();
- }
- @Override
- public void hideProcessBar() {
- progressBar.hide();
- }
- @Override
- public void showNetError() {
- Toast. makeText(this, "暂无网络", Toast.LENGTH_SHORT).show();
- }
- @Override
- public void startNextActivity() {
- Toast. makeText(this, "跳到下个activity", Toast.LENGTH_SHORT).show();
- }
==========
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 Logic
和Business 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博客的更多相关文章
- mongodb丢失数据的原因剖析 - 迎风飘来的专栏 - CSDN博客 https://blog.csdn.net/yibing548/article/details/50844310
mongodb丢失数据的原因剖析 - 迎风飘来的专栏 - CSDN博客 https://blog.csdn.net/yibing548/article/details/50844310
- Docker安装elasticsearch-head监控ES步骤 - gmijie的专栏 - CSDN博客
原文:Docker安装elasticsearch-head监控ES步骤 - gmijie的专栏 - CSDN博客 Docker安装elasticsearch-head监控ES步骤 docker拉取镜像 ...
- 记一次压测问题定位: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 ...
- 【转】Android Building System 总结 - 一醉千年 - CSDN博客
原文网址:http://www.360doc.com/content/15/0314/23/1709014_455175716.shtml Android Building System 总结 收藏 ...
- Android中MVP模式与MVC模式比較(含演示样例)
原文链接 http://sparkyuan.me/ 转载请注明出处 MVP 介绍 MVP模式(Model-View-Presenter)是MVC模式的一个衍生. 主要目的是为了解耦,使项目易于维护. ...
- android中MVP模式
http://blog.csdn.net/ysh06201418/article/details/46534799 Android App整体架构设计的思考 http://blog.csdn.ne ...
- 转----------数据库常见笔试面试题 - Hectorhua的专栏 - CSDN博客
数据库基础(面试常见题) 一.数据库基础 1. 数据抽象:物理抽象.概念抽象.视图级抽象,内模式.模式.外模式 2. SQL语言包括数据定义.数据操纵(Data Manipulation),数据控制( ...
- 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 ...
- Android开发MVP模式解析
http://www.cnblogs.com/bravestarrhu/archive/2012/05/02/2479461.html 在开发Android应用时,相信很多同学遇到和我一样的情况,虽然 ...
随机推荐
- harbor高可用集群配置
目录 说明 双主复制 主从同步 双主复制说明 多harbor实例共享后端存储 方案说明 环境说明 配置说明 安装redis和mysql 导入registry数据库 配置harbor 挂载nfs目录 修 ...
- cookie添加删除修改
//cookie添加 document.cookie="username=John Doe"; //添加过期时间 document.cookie="username1=J ...
- JXL读取,写入Excel
JXL读取,写入Excel2003 相关阅读:poi 读写excel2003:http://www.cnblogs.com/gavinYang/p/3576739.htmlpoi 读写excel200 ...
- 比特币全节点(bitcoind) eth 全节点
运行全节点的用途: 1.挖矿 2.钱包 运行全节点,可以做关于btc的任何事情,例如创建钱包地址.管理钱包地址.发送交易.查询全网的交易信息等等 选个节点钱包:bitcoind 1.配置文件: ...
- 翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化
翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化 翻译自: Exploring GLSL – Normal Visualizer with Geometry Shaders (Shader ...
- ASP.Net巧用窗体母版页
背景:每个网页的基本框架结构类似: 浏览网站的时候会发现,好多网站中,每个网页的基本框架都是一样的,比如,最上面都是网站的标题,中间是内容,最下面是网站的版权.开发提供商等信息: 在这些网页中,表头. ...
- 20155238 2016-2017-2 《Java程序设计》第五周学习总结
教材学习内容总结 Java语言中所有的错误都会包装为对象.使用try.catch可以对对象做处理. 设计错误对象都继承自java.lang.Throwable类.Throwable定义了取得错误信息, ...
- 第12月第29天 cocos quick manual
1. Example: $ cd cocos2d-x $ ./setup.py $ source FILE_TO_SAVE_SYSTEM_VARIABLE $ cocos new MyGame -p ...
- parallelogram
The parallelogram law in inner product spaces Vectors involved in the parallelogram law. In a normed ...
- 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) -- ...