MVP简单入门(附视频资料)

时间:2022-04-07 21:12:42

为什么使用MVP?

一般在Activity中既要写关于界面渲染 用户处理的代码 又要处理关于网络 数据库的请求,如果一个界面的功能复杂,那么就很容易在Activity中造成代码混乱,引用MVP 可以使代码结构逻辑更加清晰,业务逻辑与界面的剥离,解耦。

MVP实际上分为三个概念

  • View 对应于Activity、Fragment,负责View的绘制以及与用户交互
  • Model 业务逻辑和实体模型
  • Presenter 负责完成View于Model间的交互 让View与Model之间完全剥离,通过Presenter作为媒介,使两者起交互作用。

举个例子:

加载一串数据显示在TextView中,Model就是负责去加载这个数据,View就是显示TextView,如何把数据显示到TextView中呢? 就是通过Presenter去调用Model加载数据,然后通过接口返回给View。

MVP简单入门(附视频资料)

根据这上面这个例子,按照流程编写成一个简单demo(点击按钮 模拟一个网络请求 在请求的过程中展示加载框 并在数据加载完成后隐藏加载框和展示网络请求结果):

1.既然MVC是由3个模块组成,这里首先为MainActivity定义IMainView接口规范

public interface IMainView {

}

public class MainActivity extends AppCompatActivity implements IMainView {

}

2.定义布局界面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="asyncRequest"
android:text="模拟异步请求" />

<TextView
android:id="@+id/result_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

</LinearLayout>

3.初始化布局控件

public class MainActivity extends AppCompatActivity implements IMainView {

private TextView mResultTv;

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

mResultTv =(TextView) findViewById(R.id.result_tv);
}

//按钮点击事件
public void asyncRequest(View v){

}

}

4.点击按钮执行asyncRequest方法。接着由View层告诉Presenter层处理网络请求,这里先创建Presenter层,由于上面Presenter层与View层交流,所以这里Presenter层必须持有View层。代码如下。

public interface IShowPresenter {

//定义模拟的网络请求
public void doNetworkRequest();

}

public class ShowPresenterImpl implements IShowPresenter{

private IMainView mMainView;

public ShowPresenterImpl(IMainView mainView) {
mMainView=mainView;
}

@Override
public void doNetworkRequest() {

}

}

5.在View层中,onCreate()方法创建Presenter层,当点击按钮,通知Presenter层做网络请求。

public class MainActivity extends AppCompatActivity implements IMainView {
...

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

...
//初始化Presenter层
mPresenter=new ShowPresenterImpl(this);
}

public void asyncRequest(View v){
//开始网络请求
mPresenter.doNetworkRequest();
}

//显示对话框
@Override
public void showProgress(String s) {
mDialog=new ProgressDialog(this);
mDialog.setMessage(s);
mDialog.show();
}

}

public class ShowPresenterImpl implements IShowPresenter{

...

@Override
public void doNetworkRequest() {
//1.展示数据加载对话框
mMainView.showProgress("模拟数据正在加载中...");
//2.做网络请求 TODO
...
}

}

6.实际上,Presenter层只是做为一个中间件,真正的网络请求是Model层,所以这里首先创建Model层,并定义网络请求的规范。

public interface IShowModel {

void doNetworkRequest();

}

public class ShowModelImpl implements IShowModel {

private IShowListener mListener;
private Handler mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
//数据如何返回呢? (String) msg.obj
//TODO
}
};

@Override
public void doNetworkRequest() {
new Thread(){
@Override
public void run() {
SystemClock.sleep(3000);
String mockData="模拟请求的数据完毕。。。";
mHandler.obtainMessage(0,mockData).sendToTarget();
}
}.start();
}

}

6.上面的Model层提供了一个网络请求的方法doNetworkRequest(),该方法由Presenter层调用。

public class ShowPresenterImpl implements IShowPresenter,IShowModel.IShowListener{

...
private IShowModel mShowModel;

public ShowPresenterImpl(IMainView mainView) {
...
mShowModel=new ShowModelImpl(this);
}

@Override
public void doNetworkRequest() {
//1.展示数据加载对话框
...
//2.做网络请求
mShowModel.doNetworkRequest();
}

}

7.数据在Model层请求完毕后,需要将数据告诉Presenter层先,这里定义了一个回调接口。

public interface IShowModel {

...

public static interface IShowListener{

void onNetworkRequestFinish(String result);

}
}

8.Presenter是被通知的对象,所以也是回调接口的继承者,继承了回调接口后还要通知Model层。
public class ShowPresenterImpl implements IShowPresenter,IShowModel.IShowListener{

    public ShowPresenterImpl(IMainView mainView) {
...
//将回调接口告诉Model层
mShowModel=new ShowModelImpl(this);
}

//实现回调接口的方法
@Override
public void onNetworkRequestFinish(String result) {
...
}

}

9.Model层数据请求结束后 通过回调接口告诉Presenter层。

public class ShowModelImpl implements IShowModel {

private IShowListener mListener;
private Handler mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
//数据如何返回呢?
if (mListener!=null){
mListener.onNetworkRequestFinish((String) msg.obj);
}
}
};

public ShowModelImpl(IShowListener mListener) {
this.mListener = mListener;
}

...

}

10.Presenter接收到网络请求的接口 告诉View层隐藏记载框并且修改显示的UI。

public class ShowPresenterImpl implements IShowPresenter,IShowModel.IShowListener{

...

@Override
public void onNetworkRequestFinish(String result) {
//3.修改UI
mMainView.resetResultTv(result);
//4.隐藏数据加载的对话框
mMainView.hideProgress();
}

}

public class MainActivity extends AppCompatActivity implements IMainView {

...

@Override
public void hideProgress() {
if (mDialog!=null){
mDialog.dismiss();
}
}

@Override
public void resetResultTv(String result) {
mResultTv.setText(result);
}

}

示例结果:
MVP简单入门(附视频资料)

总结

感觉上单纯为了简单的实现,而去写这么多的代码,但是逻辑和结构上是更加地清晰了,业务和界面实现的方式完全剥离开。在实际的项目中这种做法更利于后期的开发和维护。

视频资料: http://pan.baidu.com/s/1gfgHH0R