MVC-MVP
任何架构的设计目的都是为了:低耦合,高复用,易测试,好维护。
MVC
MVC(Model View Controller),是软件架构中最常见的一种框架,简单来说就是通过Controller的控制去操作Model的数据,并返回给View展示。
MVC.png
View层一般采用XMl文件进行界面的描述;
Module则对应本地数据文件或者网络获取的数据体;
Controller部分则由Activity承担;
这个框架并非我们自己完成的,而是由framework给我们搭建好并提供给我们。
setContentView的作用???
在Android中MVC并不完美,View既依赖于Controller又依赖于Model,View同时含有Controller与Model的引用;UI逻辑同时存在于View与Model之间导致业务逻辑与UI逻辑无法分离,在修改UI逻辑时, 也需要修改Model, 降低了架构的灵活性,增加模块耦合, 影响重构。
MVP
MVP作为MVC的演化,解除了View和Module的耦合,同时又带来了良好的可扩展性,可测试性。对于Android来说,MVP的Model层相对于MVC是一样的,而activity/fragment不再是Controller层,而是纯粹的view层,所有关于用户事件的转发全部交由Presenter层处理。
MVP与MVC最大的区别在于Model与View之间的交互由Presenter完成而Presenter与View之间的交互是通过接口的方式。
Google官方相关MVP样例
来自官网的架构图
图中除了Activity/Fragment的黄色部分外都算是Model数据层,REPOSITORY是用来管理数据存储的,Remote data source和Local data source分别代表远程(网络)和本地(SQL)的数据来源。
以登录为例
按照MVP的思路:
这里我创建了一个CallBack,在Callback中定义数据请求的各种反馈状态,方便Model层向Presenter层反馈请求信息。
/**
* @Author: chichapaofan
* @CreateDate: 2018/11/1
* @Description: 请求结果
*/
public interface CallBack {
/**
* 请求成功
*
* @param date
*/
void onSuccess(String date);
/**
* 请求成功,无法正常返回数据
*
* @param msg
*/
void onFailure(String msg);
/**
* 请求数据失败
*/
void onError();
/**
* 请求结束,无论成功失败
*/
void onFinish();
}
Model
在Model类中进行具体的网络请求操作。通过判断请求的参数反馈不同的请求状态。
/**
* @Author: chichapaofan
* @CreateDate: 2018/11/1
* @Description: Model层
*/
public class LoginModel {
/**
* 获取数据
*
* @param param
* @param callBack
*/
public static void getData(final String param, final CallBack callBack) {
//模拟网络请求
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (param.equals("normal")) {
callBack.onSuccess("参数:" + param + "/请求结果:网络数据成功");
} else if (param.equals("failure")) {
callBack.onFailure("参数:" + param + "/请求结果:参数有误");
} else if (param.equals("error")) {
callBack.onError();
}
callBack.onFinish();
}
}, 3000);
}
}
View
View接口的作用是根据具体业务的需要,为Presenter提供调用Activity中具体UI逻辑操作的方法。
/**
* @Author: chichapaofan
* @CreateDate: 2018/11/1
* @Description:View层
*/
public interface LoginView {
/**
* 显示正在加载进度框
*/
void showLoading();
/**
* 隐藏正在加载进度框
*/
void hideLoading();
/**
* 请求成功展示数据
*/
void showData(String data);
/**
* 展示失败信息
*/
void showFailureMessage(String msg);
/**
* 数据请求异常调用此接口
*/
void showError();
}
Presenter
Presenter类是具体的逻辑业务处理类,负责请求数据,处理数据请求的反馈。
为了能够通过View接口通知Activity进行更新界面等操作,需要在Presenter类的构造方法中传递一个View接口的参数。
/**
* @Author: chichapaofan
* @CreateDate: 2018/11/1
* @Description:Persenter层
*/
public class LoginPresenter {
private LoginView loginView;
public LoginPresenter(LoginView loginView) {
this.loginView = loginView;
}
public void getData(String param) {
//展示加载
loginView.showLoading();
LoginModel.getData(param, new CallBack() {
@Override
public void onSuccess(String date) {
loginView.showData(date);
}
@Override
public void onFailure(String msg) {
loginView.showFailureMessage(msg);
}
@Override
public void onError() {
loginView.showError();
}
@Override
public void onFinish() {
loginView.hideLoading();
}
});
}
}
在Activity中
在Activity代码中如果想要调用Presenter就要先实现Presenter需要的View接口。
public class LoginActivity extends AppCompatActivity implements LoginView {
private LoginPresenter loginPresenter;
private AutoCompleteTextView mEmailView;
private EditText mPasswordView;
private View mProgressView;
private View mLoginFormView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login2);
mEmailView = findViewById(R.id.email);
mPasswordView = findViewById(R.id.password);
mProgressView = findViewById(R.id.login_progress);
mLoginFormView = findViewById(R.id.email_sign_in_button);
//
loginPresenter=new LoginPresenter(this);
mLoginFormView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//
if(mEmailView.getText().toString().equals("normal")){
loginPresenter.getData("normal");
}else if(mEmailView.getText().toString().equals("failure")){
loginPresenter.getData("failure");
}else if(mEmailView.getText().toString().equals("error")){
loginPresenter.getData("error");
}
}
});
}
@Override
public void showLoading() {
mProgressView.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading() {
mProgressView.setVisibility(View.INVISIBLE);
}
@Override
public void showData(String data) {
Toast.makeText(this, data, Toast.LENGTH_SHORT).show();
}
@Override
public void showFailureMessage(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
@Override
public void showError() {
Toast.makeText(this, "服务器开小差惹", Toast.LENGTH_SHORT).show();
}
}
到此简单的MVP架构实现完成!!