一步步搭建MVP架构

版权声明:有需要的请联系QQ1634475153,欢迎技术交流 https://blog.csdn.net/jinmie0193/article/details/82316901

MVC MVP MVVM (图文):https://blog.csdn.net/jinmie0193/article/details/81531907

MVC MVP MVVM (代码):https://blog.csdn.net/jinmie0193/article/details/81536793

本文代码下载:https://download.csdn.net/download/jinmie0193/10641441

目录

简单介绍MVP

MVP实战

场景需求

MVP模式包的组织

View层的接口定义及实现

定义接口

实现接口

Model层的接口定义及实现

定义接口

实现接口

Presenter代码及实现

Presenter与View的通信

1. View—–>Presenter

2. presenter—–>View

3. Presenter—->Model

4. Model—–>Presenter

5. Presenter代码实现

View层接口具体实现

总结


简单介绍MVP

推荐github上的一个第三方库Mosby,通过这个库大家可以很轻松的实现MVP。

流程:

和MVC最大的不同,MVP把activity作为了view层,

view层activity没有任何和model层相关的逻辑代码,取而代之的是把代码放到了presenter层中,

presenter获取了model层的数据之后,通过接口的形式将view层需要的数据返回给它就OK了。

这样的好处是什么呢?

首先,activity的代码逻辑减少了

其次,view层和model层完全解耦,

如果你需要测试一个http请求是否顺利,你不需要写一个activity,只需要写一个java类,实现对应的接口,presenter获取了数据自然会调用相应的方法,

相应的,你也可以自己在presenter中mock(虚拟)数据,分发给view层,用来测试布局是否正确。

MVP实战

在现在的公司项目中,我已经用上了MVP模式开发。但是在这里,我不想照搬代码。主要是因为怕复杂的代码或者其它的知识点干扰MVP本身的脉络。所以,我用一个简单的DEMO来讲解,大家一看就明白。

场景需求

假设现在需要做一款APP,就是显示天气,界面很简单,一个TextView显示天气信息,一个Button用来请求实时天气。 

软件启动后,会自动获取天气,然后TextView就可以显示信息。而用户点击获取实时天气的按钮,界面上会弹出正在获取中的进度对话框,等待数据加载成功后,对话框消失。Textview显示就新的天气情况。 
这里写图片描述

MVP模式包的组织

View层的接口定义及实现

在MVP中Activity用来专注视图的表现。 
而在本例子中View的表现有哪些呢?View的表现当然要用View.interface接口来定义 

View层功能模块分析

1.更新天气

2.显示获取信息等待对话框

3.取消显示对话框

定义接口

public interface WeatherViewInterface {
    /*更新天气*/
    public void updateWeather(String info);
    /*显示获取信息等待对话框*/
    public void showWaitingDialog();
    /*取消显示对话框*/
    public void dissmissDialog();
}

实现接口

public class MainProgramEntry extends AppCompatActivity implements WeatherViewInterface {



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

    }

    @Override
    public void updateWeather(final String info) {

    }

    @Override
    public void showWaitingDialog() {

    }

    @Override
    public void dissmissDialog() {

    }


}

具体的业务代码,我们等会再实现。

Model层的接口定义及实现

Model层是数据层,用来存储数据并且提供数据。在这里为了便于演示,数据被简化为了String类型。 

Model层功能模块分析

1.提供数据

2.存储数据

定义接口

public interface WeatherModelInterface {
    /*提供数据*/
    public String getInfo();
    /*存储数据*/
    public void setInfo(String info);
}

实现接口

public class WeatherModel implements WeatherModelInterface {

    private String weatherInfo;
    @Override
    public String getInfo() {
        return  weatherInfo;
    }

    @Override
    public void setInfo(String info) {
        weatherInfo = info;
    }
}

Presenter代码及实现

Presenter是个大忙人,因为要同时对View和Model对接,所以内部必须持有它们的接口引用。 
所以有如下:

public class WeatherPresenter {
    WeatherViewInterface viewInterface;
    WeatherModelInterface modelInterface;
}

Presenter与View的通信

1. View—–>Presenter

从视图界面出发,用户要请求数据,而Presenter是具体实现者,所以Presenter要提供方法代View的实现者调用,并且View的实现中必须要有Presenter的引用。 
所以MainProgramEntry .java中要有WetherPresenter的引用。

public class MainProgramEntry extends AppCompatActivity implements WeatherViewInterface{
    ......
    WeatherPresenter weatherPresenter;
    ......
}    

而Presenter也要开发API供View调用。 
所以Presenter要有requestWetherInfo()方法:

public class WetherPresenter {
    WeatherViewInterface viewInterface;
    WeatherModelInterface modelInterface;

    /*供View层调用,用来请求天气数据*/
    public void requestWeatherInfo(){
         。。。。
    }


}

2. presenter—–>View

presenter操作View,是通过View.interface,也就是View层定义的接口。 
所以很容易得到下面的代码:

public class WetherPresenter {

    ......
    private void showWaitDialog(){
        if (viewInterface != null){
            viewInterface.showWaitingDialog();
        }
    }

    private void dissmissDialog(){
        if (viewInterface != null){
            viewInterface.dissmissDialog();
        }
    }

    private void updateWeather(String info){
        if (viewInterface != null){
            viewInterface.updateWeather(info);
        }
    }
    ......
}

因为Presenter持有View的引用,所以在这里要将View.interface注入到Presenter当中。同时也需要实例化Model.interface,以便操作数据。

public class WetherPresenter {
    WeatherViewInterface viewInterface;
    WeatherModelInterface modelInterface;

    ......
    public WeatherPresenter(WeatherViewInterface viewInterface){
        this.viewInterface = viewInterface;
        modelInterface = new WeatherModel();
    }
    ......
}

Presenter与Model的通信

Presenter与Model的通信也是双方的。

3. Presenter—->Model

presenter获取到了数据,可以交给Model处理。

    private void setInfo(String info){
        modelInterface.setInfo(info);
    }

4. Model—–>Presenter

Model处理完数据后它也能对Presenter提供数据。Presenter可以通过Model对象获取本地数据。

WetherPresenter.java

    /*Model处理完数据后,它也能对Presenter提供数据*/
    private String getInfo(){
        return modelInterface.getInfo();
    }

5. Presenter代码实现

前面已经讲了Presenter与Model,Presenter与View之间的通信,现在就可以编写代码将它们粘合起来。 
Presenter本身需要向服务器获取代码,所以还要编写它的相应方法:

    /*供View层调用,用来请求天气数据*/
    public void requestWeatherInfo(){
        getNetWorkInfo();
    }

    public void getNetWorkInfo(){
        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    /*打开对话框*/
                    showWaitDialog();
                    /*模拟网络耗时*/
                    Thread.sleep(6000);

                    /*随机天气*/
                    String weatherInfo = "12度,多云";
                    Random r = new Random();
                    int seed = r.nextInt(3);

                    if(seed % 2 == 0){
                        weatherInfo = "21度,晴转多云";
                    }else{
                        weatherInfo = "22度,晴";
                    }

                    /*保存到model层*/
                    setInfo(weatherInfo);
                    /*从Model层获取数据*/
                    String localInfo = getInfo();

                    /*通知View层改变视图*/
                    updateWeather(localInfo);
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    /*取消对话框*/
                    dissmissDialog();
                }
            }//run
        }).start();
    }

View层接口具体实现

1.生成Presenter。这个在Activity中的onCreate方法中,并把自身当成IWetherView注入到presenter当中。

/*把自身当成 WeatherViewInterface 注入到presenter当中*/
weatherPresenter = new WeatherPresenter(this);

2 . 操作Presenter。当用户点击按钮时,通过调用mPresenter获取数据,然后静待更新。

    @OnClick({R.id.lable, R.id.tv_info, R.id.btn_request})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.lable:
                break;
            case R.id.tv_info:
                break;
            case R.id.btn_request:
                /*用户点击按钮调用Presenter获取数据,然后静待更新*/
                weatherPresenter.requestWeatherInfo();
                break;
        }
    }

View.interface回调方法被触发时,进行相应的视图更新。 

这里主要的视图有 

显示对话框

取消对话框

显示 天气信息。

对应代码如下:

    @Override
    public void updateWeather(final String info) {
        LogUtils.eTag("Liang","updateWeather: "+info);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tvInfo.setText(info);
            }
        });
    }

    @Override
    public void showWaitingDialog() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (mDialog != null && mDialog.isShowing()){
                    mDialog.dismiss();
                }
                mDialog = ProgressDialog.show(MainProgramEntry.this,"获取天气","正在获取...");
            }
        });
    }

    @Override
    public void dissmissDialog() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if(mDialog != null && mDialog.isShowing()){
                    mDialog.dismiss();
                }
            }
        });
    }

效果如上面的: 
这里写图片描述

总结

mvp非常适合大型的APP开发,越复杂它的优势越明显,但是如果APP代码本身很简明,mvp就有点绕弯子的感觉了

猜你喜欢

转载自blog.csdn.net/jinmie0193/article/details/82316901