MVP简介
MVP的出发点是关注点分离,将视图和业务逻辑解耦。Model-View-Presenter三个部分可以简单理解为:
- Model是将在视图中显示的数据。
- View是显示数据(model)的界面,同时将用户指令(事件)发送给Presenter来处理。View通常含有Presenter的引用。在Android中Activity,Fragment和ViewGroup都扮演视图的角色。
- Presenter是中间人,同时有两者的引用。请注意单词model非常有误导性。它应该是获取或处理model的业务逻辑。例如:如果你的数据库表中存储着User,而你的视图想显示用户列表,那么Presenter将有一个数据库业务逻辑(例如DAO)类的引用,Presenter通过它来查询用户列表。
我们大致了解到了MVP模式理论基础是怎么的,那么现在我们通过一个登录注册的demo来进行分析,
在我们还是小白或者不懂mvx结构的时候,我们一般情况下都会将视图处理,逻辑业务,数据请求等全部都放在activity处理,这就导致了整个activity臃肿不堪,并且不便与修改等操作。基本上就是这个样子。
public class RegisterActivity extend AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
//依赖了黄油刀,并且自定义了dialogfragment来提示用户操作是否成功
}
@OnClick(R.id.btn_Register)
public void onClick() {
// 账号和密码是否符合规范
if (RegexUtils.verifyUsername(mUserName)!=RegexUtils.VERIFY_SUCCESS){
// 账号不合规范时显示一个对话框提示
AlertDialogFragment.getInstances(getString(R.string.username_error),getString(R.string.username_rules))
.show(getSupportFragmentManager(),"usernameError");
return;
}
// 密码不合规范时显示一个另一个对话框提示
if (RegexUtils.verifyPassword(mPassword)!=RegexUtils.VERIFY_SUCCESS){
AlertDialogFragment.getInstances(getString(R.string.password_error),getString(R.string.password_rules))
.show(getSupportFragmentManager(),"passwordError");
return;
}
// 如果都符合正确注册规则,进行注册的业务,我们写一个异步任务来模拟登录的网络请求
public void onClick() {
// 账号和密码是否符合规范
if (RegexUtils.verifyUsername(mUserName)!=RegexUtils.VERIFY_SUCCESS){
// 账号不合规范时显示一个对话框提示
AlertDialogFragment.getInstances(getString(R.string.username_error),getString(R.string.username_rules))
.show(getSupportFragmentManager(),"usernameError");
return;
}
// 密码不合规范时显示一个另一个对话框提示
if (RegexUtils.verifyPassword(mPassword)!=RegexUtils.VERIFY_SUCCESS){
AlertDialogFragment.getInstances(getString(R.string.password_error),getString(R.string.password_rules))
.show(getSupportFragmentManager(),"passwordError");
return;
}
// 如果都符合正确注册规则,进行注册的业务,我们写一个异步任务来模拟登录的网络请求
new AsyncTask<Void, Integer, Void>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
// 进度条展示
showProgress();
}
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// 拿到数据处理UI
// 隐藏进度、显示信息、跳转页面
hideProgress();
showMessage("注册成功");
navigateToHome();
}
}.execute();
}
这样看起来并没有什么不对,但是慢慢的你会发现,当本activity里面的代码、业务逻辑等多起来,出错之后就不好找错误的地方,并且看起来非常不舒服,所以此时,mvp模式就起到了作用了。
@Override
protected void onPreExecute() {
super.onPreExecute();
// 进度条展示
showProgress();
}
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// 拿到数据处理UI
// 隐藏进度、显示信息、跳转页面
hideProgress();
showMessage("注册成功");
navigateToHome();
}
}.execute();
}
这样看起来并没有什么不对,但是慢慢的你会发现,当本activity里面的代码、业务逻辑等多起来,出错之后就不好找错误的地方,并且看起来非常不舒服,所以此时,mvp模式就起到了作用了。
首先我们要理清思路
1. View:Activity里面,我们需要获取数据,所以通过一个业务类实现
2. Presneter:业务类里面,去执行业务拿到View需要的数据
3. 拿到数据之后,数据要给视图View设置上
2. Presneter:业务类里面,去执行业务拿到View需要的数据
3. 拿到数据之后,数据要给视图View设置上
我们的目的是想要把视图和业务分离
不建议直接拿视图的对象来操作,接口:接口回调
在业务过程中视图的操作:定义一个接口
1.注册的视图接口
public interface RegisterView {
public interface RegisterView {
void showProgress();// 显示进度
void hideProgress();// 隐藏进度
void showMessage(String msg);// 显示信息
void navigateToHome();// 跳转页面
}
2.将之前我们的activity做成View层
public class RegisterActivity extend AppCompatActivity implements RegisterView{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
//依赖了黄油刀,并且自定义了dialogfragment来提示用户操作是否成功
}
@OnClick(R.id.btn_Register)
public void onClick() {
// 账号和密码是否符合规范
if (RegexUtils.verifyUsername(mUserName)!=RegexUtils.VERIFY_SUCCESS){
// 账号不合规范时显示一个对话框提示
AlertDialogFragment.getInstances(getString(R.string.username_error),getString(R.string.username_rules))
.show(getSupportFragmentManager(),"usernameError");
return;
}
// 密码不合规范时显示一个另一个对话框提示
if (RegexUtils.verifyPassword(mPassword)!=RegexUtils.VERIFY_SUCCESS){
AlertDialogFragment.getInstances(getString(R.string.password_error),getString(R.string.password_rules))
.show(getSupportFragmentManager(),"passwordError");
return;
}
// 如果都符合正确注册规则,进行注册的业务
public void onClick() {
// 账号和密码是否符合规范
if (RegexUtils.verifyUsername(mUserName)!=RegexUtils.VERIFY_SUCCESS){
// 账号不合规范时显示一个对话框提示
AlertDialogFragment.getInstances(getString(R.string.username_error),getString(R.string.username_rules))
.show(getSupportFragmentManager(),"usernameError");
return;
}
// 密码不合规范时显示一个另一个对话框提示
if (RegexUtils.verifyPassword(mPassword)!=RegexUtils.VERIFY_SUCCESS){
AlertDialogFragment.getInstances(getString(R.string.password_error),getString(R.string.password_rules))
.show(getSupportFragmentManager(),"passwordError");
return;
}
// 如果都符合正确注册规则,进行注册的业务
new RegisterPresenter(this).register();
}
3.注册的业务类
public class RegisterPresenter {
private RegisterView mRegisterView;
public RegisterPresenter(RegisterView registerView) {
mRegisterView = registerView;
}
注册的业务实现
public void register(){
new AsyncTask<Void, Integer, Void>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
// 进度条展示
mRegisterView.showProgress();
}
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// 拿到数据处理UI
// 隐藏进度、显示信息、跳转页面
mRegisterView.hideProgress();
mRegisterView.showMessage("注册成功");
mRegisterView.navigateToHome();
}
}.execute();
}
}
public class RegisterPresenter {
private RegisterView mRegisterView;
public RegisterPresenter(RegisterView registerView) {
mRegisterView = registerView;
}
注册的业务实现
public void register(){
new AsyncTask<Void, Integer, Void>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
// 进度条展示
mRegisterView.showProgress();
}
@Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// 拿到数据处理UI
// 隐藏进度、显示信息、跳转页面
mRegisterView.hideProgress();
mRegisterView.showMessage("注册成功");
mRegisterView.navigateToHome();
}
}.execute();
}
}
到这里我们基本实现了注册的一个请求了,不过可能大家也有点晕了,现在就来给大家解释一波,首先可以看到我们的View层也就是activity实现了RegisterView这个接口,而这个接口时做什么的呢,其实就是一个视图接口,我们在其中定义一些方法,比如显示隐藏进度条,设置数据等,然后在它的实现类去实现接口中的方法。
我们可以看到,在注册的时候,当我们的账号密码格式正确时,就会走到这一步,new RegisterPresenter(this).register()。这是什么意思呢?!我们再看一下RegisterPresenter这个业务类,里面构造要求传一个视图对象接口,而我们的activity是实现了这个视图接口的,所以当我们调用RegisterPresenter的构造时,只需要传入activity本身就可以了,并且当我们调用业务类中的register()方法时会执行如mRegisterView.navigateToHome()的一些方法,也就是我们构造传过来的视图接口的实现类对象.navigateToHome()这个方法,activity这个实现类又是实现了视图接口中的方法,所以也就等价于activity调用了.navigateToHome()这个方法。
这个时候我们想要的效果有了,业务逻辑与视图间的分离也实现了,
我们也就
达到了想要的目的了。登录的MVP架构也类似,大家可以试一试。
到此,这个简单的MVP架构讲解也就结束了,希望大家多多指正错误,谢谢!!!