来自于郭大侠:MVC、MVP、MVVM,谈谈我对Android应用架构的理解
结论:
MVC:Model-View-Controller,经典模式,很容易理解,主要缺点有两个:
- View对Model的依赖,会导致View也包含了业务逻辑;
- Controller会变得很厚很复杂。
MVP:Model-View-Presenter,MVC的一个演变模式,将Controller换成了Presenter,主要为了解决上述第一个缺点,将View和Model解耦,不过第二个缺点依然没有解决。
一个获取天气的例子(数据来自阿里的聚合)
MVC
public interface IWeatherModel {
void getWeather( String cityNumber, OnWeatherListener listener);
}
public class WeatherModelImpl implements IWeatherModel {
public static final String TAG = "WeatherModelImpl";
@Override
public void getWeather(String cityNumber, final OnWeatherListener listener) {
final Handler mHandler = new Handler();
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
.url("http://apis.juhe.cn/simpleWeather/query?city=" + cityNumber + "&key=天气预报的key值")
.get()//默认就是GET请求,可以不写
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
Log.d(TAG, "onFailure: ");
mHandler.post(new Runnable() {
@Override
public void run() {
listener.onError();
}
});
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
// response.body().string()只能调用一次
String responseStr = response.body() != null ? response.body().string() : "";
Log.d(TAG, "onResponse: " + responseStr);
if (response.body() != null) {
final Weather weather = JSON.parseObject(responseStr, Weather.class);
mHandler.post(new Runnable() {
@Override
public void run() {
listener.onSuccess(weather);
}
});
}
}
});
}
}
public class MainActivity extends AppCompatActivity implements OnWeatherListener {
private IWeatherModel mWeatherModel;
private EditText etCity;
private TextView tvResult;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mWeatherModel = new WeatherModelImpl();
initView();
}
//初始化View
private void initView() {
etCity = findView(R.id.et_city);
tvResult = findView(R.id.tv_result);
}
//显示结果
public void displayResult(Weather weather) {
tvResult.setText(weather.getReason());
}
@SuppressWarnings("unchecked")
private <T> T findView(int id) {
return (T) findViewById(id);
}
@Override
public void onSuccess(Weather weather) {
displayResult(weather);
}
@Override
public void onError() {
Toast.makeText(this, "获取天气信息失败", Toast.LENGTH_SHORT).show();
}
public void go(View view) {
mWeatherModel.getWeather(etCity.getText().toString().trim(), this);
}
public void mvp(View view) {
startActivity(new Intent(this, MvpActivity.class));
}
}
例子分析:
- activity里面的控件必须关心业务和数据,才能知道自己怎么展示。换句话说,我们很难让两个人在不互相沟通的情况下,一人负责获取数据,一人负责展示UI,然后完成这个功能。
- 所以的逻辑都在activity里面。
MVP
MVP从MVC进化而来,View被拆成了Presenter和View,实现了逻辑处理和View的分离
public interface IWeatherView {
String getCity();
void setText(Weather weather);
void showLoading();
void hideLoading();
void getError();
}
public class MvpActivity extends AppCompatActivity implements IWeatherView {
private EditText etCity;
private TextView tvResult;
private ProgressBar pbLoading;
private WeatherPresenter mPresenter = new WeatherPresenter(this);
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvp);
initView();
}
//初始化View
private void initView() {
etCity = findView(R.id.et_city);
tvResult = findView(R.id.tv_result);
pbLoading = findView(R.id.pb_loading);
}
@SuppressWarnings("unchecked")
private <T> T findView(int id) {
return (T) findViewById(id);
}
public void go(View view) {
mPresenter.getWeather();
}
@Override
public String getCity() {
return etCity.getText().toString();
}
@Override
public void setText(Weather weather) {
tvResult.setText(weather.getReason());
}
@Override
public void showLoading() {
pbLoading.setVisibility(View.VISIBLE);
}
@Override
public void hideLoading() {
pbLoading.setVisibility(View.GONE);
}
@Override
public void getError() {
Toast.makeText(this, "获取失败", Toast.LENGTH_LONG).show();
}
}
public class WeatherPresenter {
private IWeatherModel mModel;
private IWeatherView mView;
public WeatherPresenter(IWeatherView mView) {
this.mModel = new WeatherModelImpl();
this.mView = mView;
}
public void getWeather() {
mView.showLoading();
mModel.getWeather(mView.getCity(), new OnWeatherListener() {
@Override
public void onSuccess(Weather weather) {
mView.hideLoading();
mView.setText(weather);
}
@Override
public void onError() {
mView.hideLoading();
mView.getError();
}
});
}
}
例子分析:
- 定义了 IWeatherView 这个接口(协议),activity里面的控件不需要关心数据,只要实现这个接口在每个方法中“按部就班”的展示UI就行了。
- MVP成功解决了MVC的第一个缺点,但是逻辑处理还是杂糅在Activity。
下面是例子中的实体类和回调接口:
public class Weather {
/**
* reason : 查询成功
* result : {"city":"苏州","realtime":{"temperature":"4","humidity":"82","info":"阴","wid":"02","direct":"西北风","power":"3级","aqi":"80"},"future":[{"date":"2019-02-22","temperature":"1/7℃","weather":"小雨转多云","wid":{"day":"07","night":"01"},"direct":"北风转西北风"},{"date":"2019-02-23","temperature":"2/11℃","weather":"多云转阴","wid":{"day":"01","night":"02"},"direct":"北风转东北风"},{"date":"2019-02-24","temperature":"6/12℃","weather":"多云","wid":{"day":"01","night":"01"},"direct":"东北风转北风"},{"date":"2019-02-25","temperature":"5/12℃","weather":"小雨转多云","wid":{"day":"07","night":"01"},"direct":"东北风"},{"date":"2019-02-26","temperature":"5/11℃","weather":"多云转小雨","wid":{"day":"01","night":"07"},"direct":"东北风"}]}
* error_code : 0
*/
private String reason;
private ResultBean result;
private int error_code;
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public ResultBean getResult() {
return result;
}
public void setResult(ResultBean result) {
this.result = result;
}
public int getError_code() {
return error_code;
}
public void setError_code(int error_code) {
this.error_code = error_code;
}
public static class ResultBean {
/**
* city : 苏州
* realtime : {"temperature":"4","humidity":"82","info":"阴","wid":"02","direct":"西北风","power":"3级","aqi":"80"}
* future : [{"date":"2019-02-22","temperature":"1/7℃","weather":"小雨转多云","wid":{"day":"07","night":"01"},"direct":"北风转西北风"},{"date":"2019-02-23","temperature":"2/11℃","weather":"多云转阴","wid":{"day":"01","night":"02"},"direct":"北风转东北风"},{"date":"2019-02-24","temperature":"6/12℃","weather":"多云","wid":{"day":"01","night":"01"},"direct":"东北风转北风"},{"date":"2019-02-25","temperature":"5/12℃","weather":"小雨转多云","wid":{"day":"07","night":"01"},"direct":"东北风"},{"date":"2019-02-26","temperature":"5/11℃","weather":"多云转小雨","wid":{"day":"01","night":"07"},"direct":"东北风"}]
*/
private String city;
private RealtimeBean realtime;
private List<FutureBean> future;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public RealtimeBean getRealtime() {
return realtime;
}
public void setRealtime(RealtimeBean realtime) {
this.realtime = realtime;
}
public List<FutureBean> getFuture() {
return future;
}
public void setFuture(List<FutureBean> future) {
this.future = future;
}
public static class RealtimeBean {
/**
* temperature : 4
* humidity : 82
* info : 阴
* wid : 02
* direct : 西北风
* power : 3级
* aqi : 80
*/
private String temperature;
private String humidity;
private String info;
private String wid;
private String direct;
private String power;
private String aqi;
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
public String getWid() {
return wid;
}
public void setWid(String wid) {
this.wid = wid;
}
public String getDirect() {
return direct;
}
public void setDirect(String direct) {
this.direct = direct;
}
public String getPower() {
return power;
}
public void setPower(String power) {
this.power = power;
}
public String getAqi() {
return aqi;
}
public void setAqi(String aqi) {
this.aqi = aqi;
}
}
public static class FutureBean {
/**
* date : 2019-02-22
* temperature : 1/7℃
* weather : 小雨转多云
* wid : {"day":"07","night":"01"}
* direct : 北风转西北风
*/
private String date;
private String temperature;
private String weather;
private WidBean wid;
private String direct;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getTemperature() {
return temperature;
}
public void setTemperature(String temperature) {
this.temperature = temperature;
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
}
public WidBean getWid() {
return wid;
}
public void setWid(WidBean wid) {
this.wid = wid;
}
public String getDirect() {
return direct;
}
public void setDirect(String direct) {
this.direct = direct;
}
public static class WidBean {
/**
* day : 07
* night : 01
*/
private String day;
private String night;
public String getDay() {
return day;
}
public void setDay(String day) {
this.day = day;
}
public String getNight() {
return night;
}
public void setNight(String night) {
this.night = night;
}
}
}
}
}
public interface OnWeatherListener {
void onSuccess(Weather weather);
void onError();
}
来源:CSDN
作者:csdn1225987336
链接:https://blog.csdn.net/csdn1225987336/article/details/103461186