MVP架构的理解与实现Demo

1 MVC架构

MVC架构介绍

现在的Android程序大多采用MVC的架构,MVC的架构软件可以分为三个部分:
- 视图(View): 用户界面
- 控制器(Controller) : 业务逻辑
- 模型(Model) : 数据保存

MVC架构的核心如下图所示:
image
View传送指令到Controller, Controller完成业务逻辑后,要求Model改变状态,Model将新的数据发送到View,用户得到反馈。

MVC架构存在的问题

在MVC架构中,一般XML布局文件和Activity的setContentView等充当了View角色,Activity的其他代码充当Controller角色,其他数据来源充当了Model角色。Activity担当的责任非常之重,而且违背了单一职责原则。

MVP架构

MVP架构的软件可以分为三个部分:
- 模型(Model) 用来做实际数据的操作,又是也需要创建一个Model的抽象接口Model Interface来降低耦合。
- 视图(View) 也就是Android的Activity,同事需要创建一个View的抽象接口View Interface,需要View实现接口,View通过View Interface与Presenter进行交互,降低耦合。
- 表示层(Presenter): 作为View与Model交互的中间纽带,处理与用户交互的交互逻辑。

下图展示了MVC架构的核心:
image

MVC和MVP对比

MVP架构:
- View不直接与Model交互,而是通过与中间层Presenter交互来与Model间接交互
- Presenter与View的交互是通过接口来进行的
- 通常View与Presenter与一对一的

MVC架构:
- View可以与Model直接交互
- Controller是基于行为的,可以被多个View共享

MVP是从经典的MVC演变而来, 它们的基本思想是有想通的地方:Controller/Presenter负责逻辑的处理,MOdel提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不能直接使用Model,它们之间的通信是通过Presenter来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过Controller。

MVP架构的例子

接下来,我们将通过一个使用MVP网络请求天气预报的demo来讲解MVP架构。我们的网络请求使用OKHttp框架来做。
项目github地址: https://github.com/chengshuyuan/MVPTest.git

程序运行图

这里写图片描述
工程总共包括四个包
bean: 包含一个WeatherInfo实体类
model:项目的model层,包含一个网络请求天气预报信息的接口与实现类。
presenter: 表示层
view: 项目的view层,包括一个activity和一个view接口。

如图

这里写图片描述

1 实体类

实体类很简单,不解释

package com.secondclass.mvptest.bean;

public class WeatherInfo {
    private String city;
    private String cityid;
    private String temp1;
    private String temp2;
    private String weather;
    private String ptime;

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getCityId() {
        return cityid;
    }

    public void setCityId(String cityId) {
        this.cityid = cityId;
    }

    public String getTemp1() {
        return temp1;
    }

    public void setTemp1(String temp1) {
        this.temp1 = temp1;
    }

    public String getTemp2() {
        return temp2;
    }

    public void setTemp2(String temp2) {
        this.temp2 = temp2;
    }

    public String getPtime() {
        return ptime;
    }

    public void setPtime(String ptime) {
        this.ptime = ptime;
    }

    public String getWeather() {
        return weather;
    }

    public void setWeather(String weather) {
        this.weather = weather;
    }

    public String toString(){
        return city + temp1 + temp2 + weather + ptime;
    }
}

2 Model层

在业务层,我们抽取了一个接口,并在实现类中采用OKHttp进行网络的请求和解析,网络请求是一个耗时操作,而OKHttp框架新开了线程来进行网络的操作。

接口

package com.secondclass.mvptest.model;

public interface IWeatherModel {
    public void getWeather(String cityName, GetWeatherListener listener);
}

实现类

package com.secondclass.mvptest.model;

import com.google.gson.Gson;
import com.secondclass.mvptest.bean.WeatherInfo;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class WeatherModel implements IWeatherModel {
    OkHttpClient client = new OkHttpClient();
    private WeatherInfo weatherInfo;
    @Override
    public void getWeather(String cityName, final GetWeatherListener listener) {

        final Request request = new Request.Builder()
                //这里只做一个模拟
                .url("http://www.weather.com.cn/data/cityinfo/101010100.html")
                .build();
        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                listener.getFailed();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String responseStr = response.body().string();
                try {
                    JSONObject jsonObject = new JSONObject(responseStr);
                    JSONObject weatherJson = jsonObject.optJSONObject("weatherinfo");
                    Gson gson = new Gson();
                    weatherInfo = gson.fromJson(weatherJson.toString(), WeatherInfo.class);
                    listener.getSuccess(weatherInfo);
                }catch (Exception e){
                    e.printStackTrace();
                    listener.getFailed();
                }
            }
        });

    }
}

3 Presenter

package com.secondclass.mvptest.presenter;

import android.os.Handler;
import android.os.Looper;

import com.secondclass.mvptest.View.IWeatherView;
import com.secondclass.mvptest.bean.WeatherInfo;
import com.secondclass.mvptest.model.GetWeatherListener;
import com.secondclass.mvptest.model.IWeatherModel;
import com.secondclass.mvptest.model.WeatherModel;

public class WeatherPresenter {
    private IWeatherView weatherView;
    private IWeatherModel weatherModel;
    private Handler handler = new Handler(Looper.getMainLooper());

    public WeatherPresenter(IWeatherView weatherView){
        this.weatherModel = new WeatherModel();
        this.weatherView = weatherView;
    }

    public void getWeather(String cityName){
       weatherModel.getWeather(cityName, new GetWeatherListener() {
            @Override
            public void getSuccess(final WeatherInfo weatherInfo) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        weatherView.setWeather(weatherInfo);
                    }
                });
            }

            @Override
            public void getFailed() {

            }
        });
    }
}

这里需要注意的是OKhttp进行网络请求是在其他的线程,所以想要更新UI的时候,需要调用绑定ui线程的Handler类的post方法。

4 View

View的接口:

package com.secondclass.mvptest.View;

import com.secondclass.mvptest.bean.WeatherInfo;

public interface IWeatherView {
    public void setWeather(WeatherInfo weatherInfo);
}

View的实现类, 也就是activity

package com.secondclass.mvptest.View;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.secondclass.mvptest.R;
import com.secondclass.mvptest.bean.WeatherInfo;
import com.secondclass.mvptest.presenter.WeatherPresenter;


public class WeatherActivity extends AppCompatActivity implements IWeatherView{

    private EditText et_cityName;
    private Button btn_submit;
    TextView tv_temp1, tv_temp2, tv_weather, tv_time;
    private String cityName;
    private WeatherPresenter presenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_weather);
        presenter = new WeatherPresenter(this);
        initView();
    }

    private void initView(){
        et_cityName = (EditText)this.findViewById(R.id.et_cityname);
        btn_submit = (Button)this.findViewById(R.id.btn_submit);
        tv_temp1 = (TextView)this.findViewById(R.id.tv_temp1);
        tv_temp2 = (TextView)this.findViewById(R.id.tv_temp2);
        tv_weather = (TextView)this.findViewById(R.id.tv_weather);
        tv_time = (TextView)this.findViewById(R.id.tv_time);

        btn_submit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                cityName = et_cityName.getText().toString().trim();
                if(!TextUtils.isEmpty(cityName)) {
                    presenter.getWeather(cityName);
                }
            }
        });
    }

    @Override
    public void setWeather(final WeatherInfo weatherInfo) {
        tv_temp1.setText(weatherInfo.getTemp1());
        tv_temp2.setText(weatherInfo.getTemp2());
        tv_weather.setText(weatherInfo.getWeather());
        tv_time.setText(weatherInfo.getPtime());
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值