今天简单的来写一个MVP模式的demo,MVC跟MVP的区别网上一大堆,这里不多说;
平时我们的开发都是MVC模式的,下面我们写一个MVC的例子,然后在把它转为MVP模式,对比一下就很清楚之间的区别;
需求:页面上一个Button,点击Button发送网络请求,将请求成功后的信息用Toast弹出来;
MVC例子
public class MainActivity extends AppCompatActivity {
private Button mBtnClick;
private final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
onClickListener();
}
private void initView() {
mBtnClick = findViewById(R.id.btn_click);
}
private void onClickListener() {
mBtnClick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getData();
}
});
}
private void getData() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://wwww.baidu.com")
.get()
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i(TAG+" onFailure",e.toString());
}
@Override
public void onResponse(Call call, final Response response) throws IOException {
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, response.toString(), Toast.LENGTH_LONG).show();
}
});
}
});
}
}
MVC会将所有的业务逻辑跟数据处理都写在一起,在功能多的情况下会显示很臃肿,沉重。
下面将上面的例子转换为MVP模式,使用MVP一定会用到interface,会写比较多的interface,这也是MVP模式的缺点。为了较少的创建接口类,可以定义了一个契约接口,把它们更加紧密的结合在一起,也方便查看,如下:
public interface IMainContract {
//View层需要用到的interface
interface IMainView{
void toast(String Content);
}
//Model层需要用到的interface
interface IMainModel{
void click(Callback callback);
}
//Presenter层需要用到的interface
interface IMainPresenter{
void handlerData();
}
}
View层
因为业务逻辑在M层,数据的处理在P层,所以V层只需要将数据显示出来就行,V层会通知P层数处理数据,P层处理后会回传给V层
public class MainActivity extends AppCompatActivity implements IMainContract.IMainView {
private Button mBtnClick;
private PresenterManager mPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
mPresenter = new PresenterManager(this);
onClickListener();
}
private void initView() {
mBtnClick = findViewById(R.id.btn_click);
}
//按钮的点击事件
private void onClickListener(){
mBtnClick.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mPresenter.handlerData();//让P层去处理数据
}
});
}
@Override
public void toast(final String Content) {//用于显示数据
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, Content, Toast.LENGTH_LONG).show();
}
});
}
}
Model层
网络请求数据在这一层,代码如下:
public class ModelData implements IMainContract.IMainModel {
@Override
public void click(Callback callback) {//使用了Callback,将获取到的数据回调给presenter处理
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://wwww.baidu.com")
.get()
.build();
Call call = client.newCall(request);
call.enqueue(callback);
}
}
Presenter层
P层将从M层获取到的数据进行处理后,传给V层,V层将数据显示出来
public class PresenterManager implements IMainContract.IMainPresenter {
private IMainContract.IMainModel model;
private IMainContract.IMainView view;
public PresenterManager(IMainContract.IMainView view) {//初始化view跟model
this.view = view;
model = new ModelData();
}
@Override
public void handlerData() {
model.click(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (view != null)
view.toast(response.body().string());//让V层去更新UI
}
});
}
}
好了,这就写完了,细心的人会发现,V层跟M层之间没有直接的联系,都是通过P层来完成的,没错,因为这就是MVP模式的核心,将V-M在结构上实现分离,P层是V-M之间沟通的桥梁,所以P层中会包含V层对象跟M层对象。
总结:V层如果要更新数据,V层会通知P层,P层会去M层获取数据,然后P层再将拿到的数据传给V层,V层进而实现更新。
看了上面的例子,可能有人会提出疑问,MVC明明比MVP简单,代码少,看起来也清晰。其实是这样,因为上面的例子太过于简单,MVP一般在多功能,需求大的项目中最能提现其优势,容易维护,项目结构上也会越来越清晰。
至于用MVC还是MVP,因人而异吧。