Android -- 初探MVP模式
1,相信大家对mvp模式都很熟悉了,M-Model-模型、V-View-视图、C-Controller-控制器。MVP作为MVC的版本演化,与MVC的意义类似:M-Model-模型、V-View-视图、P-Presenter-表示器。从MVC和MVP两者结合来看,Controlller/Presenter在MVC/MVP中都起着逻辑控制处理的角色,起着控制各业务流程的作用。而 MVP与MVC最不同的一点是M与V是不直接关联的也是就Model与View不存在直接关系,这两者之间间隔着的是Presenter层,其负责调控 View与Model之间的间接交互。在 Android中很重要的一点就是对UI的操作基本上需要异步进行也就是在MainThread中才能操作UI,所以对View与Model的切断分离是 合理的。此外Presenter与View、Model的交互使用接口定义交互操作可以进一步达到松耦合也可以通过接口更加方便地进行单元测试。下面是对应的两张图(左图为mvc,右图为mvp):
可以看到最明显的区别是mvc是允许model和view交互的,而mvp中model和view中的交互是由presenter完成的,presenter和view的交互是通过接口来实现的。
2,mvp的实现应用 (例子是大神博客写的,自己只是拿过来来写一下实现的思路,毕竟还是小菜鸟的级别)
先看一下要实现的效果:
再看一下我们工程的目录:
由我们上面的功能需要可以看出,这是一个最常见的登录功能,所以首先我们要创建一个User类,,包含用户名和密码,用于对应用户输入的用户信息
① Model层
User.java
package com.wangjitao.simplelogindemo.bean; /** * Created by wangjitao on 2016/5/12. * 用户登录bean */ public class User { private String username ; private String password ; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
从上面所给的功能可以看出我们主要是要实现登录功能的,所以至少有一个login()方法
IUserBIZ.java
package com.wangjitao.simplelogindemo.inter; import com.wangjitao.simplelogindemo.listener.OnLoginListener; /** * Created by wangjitao on 2016/5/12. */ public interface IUserBIZ { public void login(String username ,String password ,OnLoginListener loginListener); }
它的实现类 UserBIZ.java ,在实现类中我们模拟一个登陆的耗时操作,然后在登录成功的写了一个回调类OnLoginListener.java
UserBIZ.java
package com.wangjitao.simplelogindemo.inter; import com.wangjitao.simplelogindemo.bean.User; import com.wangjitao.simplelogindemo.listener.OnLoginListener; /** * Created by jh on 2016/5/12. */ public class UserBIZ implements IUserBIZ{ @Override public void login(final String username, final String password, final OnLoginListener loginListener) { //开启子线程模拟登录耗时操作 new Thread(){ @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //模拟登录成功 if("wjt".equals(username) && "123456".equals(password)){ User user = new User(); user.setUsername(username); user.setPassword(password); loginListener.loginSuccess(user); }else { loginListener.loginFailed(); } } }.start(); } }
OnLoginListener.java
package com.wangjitao.simplelogindemo.listener; import com.wangjitao.simplelogindemo.bean.User; /** * Created by wangjitao on 2016/5/12. */ public interface OnLoginListener { void loginSuccess(User user) ; void loginFailed(); }
②View 层
从我们看到的界面我们可以看到,用户一共有两个按钮,一个是login,那么需要两个方法来获取用户名和密码
String getUserName(); String getPassword();
然后是一个clear按钮,这时候我们要提供两个方法去清空输入框的内容
void clearUserName(); void clearPassword();
然后当用户正在登陆的时候,我们需要一个用户的等待,这时候我们需要加一个进度的提示条
void clearUserName(); void clearPassword();
然后是用户登录后的一些提示,当登陆成功,让用户跳转到下一个界面,当登录失败提示用户用户名或密码错误
void toMainActivity(User user); void showFailedError();
所以view的接口如下:
package com.wangjitao.simplelogindemo.view; import com.wangjitao.simplelogindemo.bean.User; /** * Created by jh on 2016/5/12. */ public interface IUserLoginView { String getUserName(); String getPassword(); void showLoading(); void dismissLoading(); void toMainActivity(User user); void showFailedError(); void clearUserName(); void clearPassword(); }
然后Activity来实现这个接口的方法(Activity也可以当做一个view层)
package com.wangjitao.simplelogindemo; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.Toast; import com.wangjitao.simplelogindemo.bean.User; import com.wangjitao.simplelogindemo.presenter.UserLoginPresenter; import com.wangjitao.simplelogindemo.view.IUserLoginView; public class MainActivity extends AppCompatActivity implements IUserLoginView{ private EditText editText_username ,editText_password ; private Button button_login ,button_clean ; private ProgressBar progressBar ; private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { editText_username = (EditText)findViewById(R.id.editText_username); editText_password = (EditText)findViewById(R.id.editText_password); button_login = (Button)findViewById(R.id.button_login); button_clean = (Button)findViewById(R.id.button_clean); progressBar = (ProgressBar)findViewById(R.id.progressBar); button_login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mUserLoginPresenter.login(); } }); button_clean.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mUserLoginPresenter.clear(); } }); } @Override public String getUserName() { return editText_username.getText().toString(); } @Override public String getPassword() { return editText_password.getText().toString(); } @Override public void showLoading() { progressBar.setVisibility(View.VISIBLE); } @Override public void dismissLoading() { progressBar.setVisibility(View.GONE); } @Override public void toMainActivity(User user) { Toast.makeText(MainActivity.this ,"登录成功:欢迎回来"+user.getUsername(),Toast.LENGTH_SHORT).show(); } @Override public void showFailedError() { Toast.makeText(MainActivity.this ,"登录失败",Toast.LENGTH_SHORT).show(); } @Override public void clearUserName() { editText_username.setText(""); } @Override public void clearPassword() { editText_password.setText(""); } }
③Persenter
这个用与处数据和视图的交互,我们的这个应用主要是login和clear ,所以代码如下:
package com.wangjitao.simplelogindemo.presenter; import android.os.Handler; import com.wangjitao.simplelogindemo.bean.User; import com.wangjitao.simplelogindemo.inter.IUserBIZ; import com.wangjitao.simplelogindemo.inter.UserBIZ; import com.wangjitao.simplelogindemo.listener.OnLoginListener; import com.wangjitao.simplelogindemo.view.IUserLoginView; /** * Created by wangjitao on 2016/5/12. */ public class UserLoginPresenter { private IUserBIZ userBIZ ; private IUserLoginView userLoginView ; private Handler mHandler = new Handler(); public UserLoginPresenter(IUserLoginView userLoginView){ this.userLoginView = userLoginView ; userBIZ = new UserBIZ(); } public void login(){ userLoginView.showLoading(); userBIZ.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() { @Override public void loginSuccess(final User user) { mHandler.post(new Runnable() { @Override public void run() { userLoginView.toMainActivity(user); userLoginView.dismissLoading(); } }); } @Override public void loginFailed() { mHandler.post(new Runnable() { @Override public void run() { userLoginView.showFailedError(); userLoginView.dismissLoading(); } }); } }); } public void clear(){ userLoginView.clearUserName(); userLoginView.clearPassword(); } }
Presenter大致就是从View中获取需要的参数,交给Model去执行业务方法,执行的过程中需要的反馈,以及结果,再让View进行做对应的显示。
这样我们的demo就写完了 ,感觉还是很有成就感的嘛。