Android进阶 MVP设计模式实例
2016-08-11 16:53
549 查看
Android之MVP设计模式实例
MVP(Model View Presenter)的设计模式是从MVC中演化而来的,主要作用是能够:划分模块职责,
降低模块耦合
易测试,提高代码复用
Model:数据:负责数据的检索
View: 视图:负责视图的绘制,和用户的交互
presenter: 控制器:负责在Model和View之间交互,负责两者业务的逻辑处理
与MVC的区别:
在MVC中,在Controller中,有View和Model的部分处理逻辑,在View处理时间的过程中,也有Model操作的过程,该模式看起来模式简单,层级关系不多,而且代码量少,但是大部分逻辑都杂糅到了一起,
在测试和调试的过程中较之MVP而言很不方便
在MVC中,数据,控制器,视图之间互相操作的关系是这样的:
而在MVP中,presenter单线操作数据Model部分的数据,
同样的presenter也是单线的操作视图View模块的东西,但是中间是是通过调用接口的方式,
当View界面和数据有交互的时候,再通过接口调用Presenter,再由Presenter调用Model来进行数据的改变
在MVP中,数据,控制器,视图之间相互操作的关系是这样的:
Android代码示例
简单的演示一个登陆操作的界面,用户输入用户名密码,然后模拟操作访问服务器验证用户名密码的操作,此过程显示进度条,登陆成功之后显示成功界面,失败提示失败信息简单的看一下界面:
activity_user_login.xml:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/username" android:textSize="18sp" android:layout_alignParentLeft="true" android:layout_marginTop="20dp" android:id="@+id/id_tv_username"/> <EditText android:layout_width="170dp" android:layout_height="40dp" android:id="@+id/id_et_username" android:layout_alignParentRight="true" android:layout_marginRight="20dp" android:text="username" android:layout_alignBottom="@+id/id_tv_username" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/passwprd" android:textSize="18sp" android:layout_alignParentLeft="true" android:layout_marginTop="80dp" android:id="@+id/id_tv_password"/> <EditText android:layout_width="170dp" android:layout_height="40dp" android:id="@+id/id_et_password" android:layout_alignBottom="@id/id_tv_password" android:layout_alignParentRight="true" android:layout_marginRight="20dp" android:text="password" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/id_btn_login" android:text="Login" android:layout_below="@+id/id_et_password" android:layout_alignEnd="@+id/id_tv_username" android:layout_marginTop="35dp" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/id_btn_clear" android:text="Clear" android:layout_alignTop="@+id/id_btn_login" android:layout_alignEnd="@+id/id_et_password" android:layout_marginEnd="24dp" /> <ProgressBar style="?android:attr/progressBarStyleLarge" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/id_progressbar" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:visibility="invisible"/> </RelativeLayout>
界面效果如下:
程序运行结果预览:
界面写好之后,开始分析该程序的数据和功能:
首先,需要有一个JavaBean对象User,保存username 和password字段
需要String类型的username和password
package com.jishihuitong.mvpdemo.bean; /** * Created by hss on 2016/8/2. */ public class User { private String username; private String password; public String getUsername() { return username; } public String getPassword() { return password; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } }
然后根据视图,肯定要有一个login的方法,在MVP中presenter操作model和view的过程都是使用接口的,所以要有一个IUserModel和UserModelImpl继续完成
IUserModel类
package com.jishihuitong.mvpdemo.model; /** * Created by hss on 2016/8/2. */ public interface IUserModel { /** * 登录数据模块的操作 * @param username 用户名 * @param password 密码 * @param onLoginListener 登录监听 */ public void login(String username,String password,OnLoginListener onLoginListener); }
IUserModel实现类
package com.jishihuitong.mvpdemo.model; import com.jishihuitong.mvpdemo.bean.User; /** * Created by hss on 2016/8/2. */ public class UserModelImpl implements IUserModel { @Override public void login(final String username, final String password, final OnLoginListener onLoginListener) { new Thread(){ @Override public void run() { try { //模拟从网络加载数据,需要时间 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } if("username".equals(username) && "password".equals(password)){ User user = new User(); user.setUsername(username); user.setPassword(password); onLoginListener.loginSuccess(user); }else{ onLoginListener.loginFailed(); } } }.start(); } }
登录成功或者失败的监听
package com.jishihuitong.mvpdemo.model; import com.jishihuitong.mvpdemo.bean.User; /** * Created by hss on 2016/8/2. */ public interface OnLoginListener { /** * 登录成功 * @param user user对象 */ public void loginSuccess(User user); /** * 登录失败 */ public void loginFailed(); }
View层,上面说到,MVP设计模式中,调用View层的方法都是通过接口调用的,
所以我们需要显示定义一个View的接口ILoginVeiw,在该接口中需要有什么方法呢?
首先需要
getUsername(); getPassword();
清空输入框内容的方法
clearUsername(); clearPassword();
登录成功和登录失败的方法
toMainActivity(User user); showFailedError();
显示进度和隐藏进度的方法
showLoading(); hideLoading();
所以综合上述表述,写出来的ILoginView接口应该是这样的:
package com.jishihuitong.mvpdemo.view; import com.jishihuitong.mvpdemo.bean.User; /** * Created by hss on 2016/8/2. */ public interface IUserLoginView { /** * View层接口获取用户名的方法 * @return 输入的用户名 */ public String getUserName(); /** * View层接口获取密码的方法 * @return 输入的密码 */ public String getPassword(); /** * View层清除用户名 */ public void clearUserName(); /** * View层清除密码的方法 */ public void clearPassword(); /** * View层登录成功的方法 * @param user user对象 */ public void toMainActivity(User user); /** * View层显示登录失败的方法 */ public void showFailedError(); /** * View层显示进度条的方法 */ public void showLoading(); /** * View层隐藏进度条的方法 */ public void hideLoading(); }
而加载布局的一个类显然就是View层的了,该类要实现ILoginView接口,并且实现里面的方法:
然后登录操作,需要使用present来执行,
UserLoginActivity.java
package com.jishihuitong.mvpdemo.view; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.Toast; import com.jishihuitong.mvpdemo.R; import com.jishihuitong.mvpdemo.bean.User; import com.jishihuitong.mvpdemo.presenter.UserLoginPresenter; /** * 登录界面主activity IView的实现类, */ public class UserLoginActivity extends AppCompatActivity implements IUserLoginView { private EditText id_et_username; private EditText id_et_password; private Button id_btn_login; private Button id_btn_clear; private UserLoginPresenter mUserLoginPrestener = new UserLoginPresenter(this); private ProgressBar id_progressbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user_login); initView(); } /** * 初始化控件 */ private void initView() { id_et_username = (EditText) findViewById(R.id.id_et_username); id_et_password = (EditText) findViewById(R.id.id_et_password); id_btn_login = (Button) findViewById(R.id.id_btn_login); id_btn_clear = (Button) findViewById(R.id.id_btn_clear); id_progressbar = (ProgressBar) findViewById(R.id.id_progressbar); id_btn_login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // presenter控制逻辑 登录操作 mUserLoginPrestener.login(); } }); id_btn_clear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mUserLoginPrestener.clear(); } }); } @Override public String getUserName() { return id_et_username.getText().toString(); } @Override public String getPassword() { return id_et_password.getText().toString(); } @Override public void clearUserName() { id_et_username.setText(""); } @Override public void clearPassword() { id_et_password.setText(""); } @Override public void toMainActivity(User user) { Toast.makeText(getApplicationContext(),getUserName()+"登录成功",Toast.LENGTH_SHORT).show(); } @Override public void showFailedError() { Toast.makeText(getApplicationContext(),getUserName()+"登录失败",Toast.LENGTH_SHORT).show(); } @Override public void showLoading() { id_progressbar.setVisibility(View.VISIBLE); } @Override public void hideLoading() { id_progressbar.setVisibility(View.INVISIBLE); } }
UserLoginPresenter.java
package com.jishihuitong.mvpdemo.presenter; import android.os.Handler; import com.jishihuitong.mvpdemo.bean.User; import com.jishihuitong.mvpdemo.model.IUserModel; import com.jishihuitong.mvpdemo.model.OnLoginListener; import com.jishihuitong.mvpdemo.model.UserModelImpl; import com.jishihuitong.mvpdemo.view.IUserLoginView; /** * Created by hss on 2016/8/2. */ public class UserLoginPresenter { private IUserModel userModel; private IUserLoginView userLoginView; private Handler mHandler = new Handler() { }; public UserLoginPresenter(IUserLoginView userLoginView) { this.userModel = new UserModelImpl(); this.userLoginView = userLoginView; } /** * 登录操作 */ public void login() { // 设置进度条可见 userLoginView.showLoading(); //数据控制器控制model操作登录 userModel.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() { @Override public void loginSuccess(final User user) { //需要在UI线程执行 mHandler.post(new Runnable() { @Override public void run() { userLoginView.toMainActivity(user); userLoginView.hideLoading(); } }); } @Override public void loginFailed() { //需要在UI线程执行 mHandler.post(new Runnable() { @Override public void run() { userLoginView.showFailedError(); userLoginView.hideLoading(); } }); } }); } /** * 清除所有数据的方法 */ public void clear() { userLoginView.clearPassword(); userLoginView.clearUserName(); } }
总体来说,虽然说代码的层次增加了,代码量也增加了,但是仔细看看,是不是代码感觉特别明朗,层次感特别清晰呢,该模式主要适用于数据和view交互比较多的模块,
MVP时下很火,所以在此了解学习一下,有不足的地方,欢迎指正。
点击下载代码
相关文章推荐
- Android 设计模式之MVP,从实例中体现MVP
- Android中MVP设计模式实例
- Android开发进阶:23种设计模式一览(设计模式教你追MM)
- Android Widget进阶——桌面便笺程序实例的实现流程与美化设计(图)
- android MVP设计模式
- Android框架模式(2)-MVP进阶
- Android---MVP设计模式高级(三)
- Android之MVP设计模式
- Android设计模式之浅谈MVP
- 最常用的Java设计之一 观察者模式 在android中的实例 ListView Adapter机制
- Android中的MVP设计模式
- Android mvp 设计模式目录架构设计
- 设计模式实例学习-单例模式(Android中的使用场景)
- Android 设计模式之一:MVP模式与MVC模式
- 深入浅出单实例Singleton设计模式(Android)
- Android 中如何使用MVP设计模式
- android MVP设计模式实践
- android MVP 设计模式
- Android MVP 设计模式
- Android 设计模式之二:MVP模式与MVC模式 .