迄今为止最通俗易懂的MVP架构讲解

时间:2022-01-31 06:15:35

从MVC到MVP再到MVVP,相信大家就已经听说过这些架构了。但你真正应用到哪个阶段了呢?是不是还苦于网上对MVP晦涩的讲解?今天,Coder哥就用最通俗易懂的方式告诉你,MVP怎么用!

先上一张MVP结构图。
迄今为止最通俗易懂的MVP架构讲解

接下来就一步步教你用:

1、首先把结构包分好,方便理清思路

迄今为止最通俗易懂的MVP架构讲解

2、定义Model层的接口IModel

/**
* Model层接口---实现该接口的类负责实际的获取数据操作,如数据库读取、网络加载
*/

public interface IModel {

void getData(Model.LoadDataCallback callback);
}

然后创建Model实体类实现IModel接口,并覆写数据获取方法。

/**
* 实现IModel接口,负责实际的数据获取操作(数据库读取,网络加载等),然后通过自己的接口(LoadDataCallback)反馈出去
*/

public class Model implements IModel {


@Override
public void getData(final LoadDataCallback callback) {
//数据获取操作,如数据库查询、网络加载等
new Thread() {
@Override
public void run() {
try {
//模拟耗时操作
Thread.sleep(3000);
//获取到了数据
String data = "我是获取到的数据";
//将获取的数据通过接口反馈出去
callback.success(data);
} catch (InterruptedException e) {
e.printStackTrace();
//获取数据失败的回调
callback.failure();
}
}
}.start();
}

public interface LoadDataCallback {

void success(String taskId);

void failure();
}
}

Model层搞定!

2、定义IView接口

/**
* View层接口---执行各种UI操作,定义的方法主要是给Presenter中来调用的
*/

public interface IView {

void showLoadingProgress(String message);

void showData(String text);
}

然后创建View实体类实现IView接口,并覆写UI操作方法。

/**
* 实现IView接口并实现各种UI操作的方法(其他的业务逻辑在Presenter中进行操作)
*/

public class ViewActivity extends Activity implements IView {

private Button mBtnShowToast;
private TextView mText;
private MyHandler mHandler = new MyHandler(ViewActivity.this);

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvp);

mBtnShowToast = (Button) findViewById(R.id.btn_show_toast);
mText = (TextView) findViewById(R.id.text);
mBtnShowToast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {

}
});
}

@Override
public void showLoadingProgress(final String message) {
mHandler.post(new Runnable() {
@Override
public void run() {
mText.setText(message);
}
});
}

@Override
public void showData(final String text) {
mHandler.post(new Runnable() {
@Override
public void run() {
mText.setText(text);
}
});
}

private class MyHandler extends Handler {

//弱引用,防止内存泄露
WeakReference<ViewActivity> weakReference;

public MyHandler(ViewActivity activity) {
this.weakReference = new WeakReference<ViewActivity>(activity);
}

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
weakReference.get().mText.setText(msg.what);
break;
}
}
}
}

View层搞定!

3、定义IPresenter接口

/**
* Presenter层接口---控制Model层的数据操作及调用View层的UI操作来完成“中间人”工作
*/

public interface IPresenter {

void loadData();

}

然后创建Presenter实体类实现IPresenter接口。

public class Presenter implements IPresenter, Model.LoadDataCallback {

private final IView mView;
private final Model mModel;

public Presenter(IView view) {
mView = view;
mModel = new Model();
}

@Override
public void loadData() {
mView.showLoadingProgress("加载数据中");
mModel.getData(Presenter.this);
}

@Override
public void success(String data) {
mView.showData(data);
}

@Override
public void failure() {

}
}

4、View中实例化Presenter,通过Presenter来处理业务逻辑。最终达到,View只负责UI操作,Model只负责数据,Presenter负责链接二者的目的。

View层完整代码

/**
* 实现IView接口并实现各种UI操作的方法(其他的业务逻辑在Presenter中进行操作)
*/

public class ViewActivity extends Activity implements IView {

private Button mBtnShowToast;
private TextView mText;
private MyHandler mHandler = new MyHandler(ViewActivity.this);
private IPresenter mPresenter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvp);

//实例化Presenter,并将实现了IView接口的类传入进去
mPresenter = new Presenter(ViewActivity.this);

mBtnShowToast = (Button) findViewById(R.id.btn_show_toast);
mText = (TextView) findViewById(R.id.text);
mBtnShowToast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通过Presenter来实现业务逻辑操作,View层只负责UI相关操作
mPresenter.loadData();
}
});
}

@Override
public void showLoadingProgress(final String message) {
mHandler.post(new Runnable() {
@Override
public void run() {
mText.setText(message);
}
});
}

@Override
public void showData(final String text) {
mHandler.post(new Runnable() {
@Override
public void run() {
mText.setText(text);
}
});
}

private class MyHandler extends Handler {

//弱引用,防止内存泄露
WeakReference<ViewActivity> weakReference;

public MyHandler(ViewActivity activity) {
this.weakReference = new WeakReference<ViewActivity>(activity);
}

@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
weakReference.get().mText.setText(msg.what);
break;
}
}
}
}

大家要多看,多试验,最重要的是理解这个思路。Google官方的Todo MVP代码大家可以去研读一下,是同一个模式,只不过它把好多接口集成在一个接口文件中,防止代码碎片化,大家研读时记住这一点,就不会困惑了。

最后附上Google MVP的代码地址:

https://github.com/googlesamples/android-architecture/tree/todo-mvp/