上一篇文章中写了 MVC,Controller 层作为 View 层和 Model 层交互的链接,它从 View 层获取到用户输入交由 Model 层去处理,Model 层处理过后的数据又经过 Controller 层交由 View 层去显示。根据业务的不同,各层之间也存在着一定的耦合。
随着业务的增加,页面中 Controller 中的代码会逐渐增加,变得臃肿。于是 MVP 就产生并逐渐成为主流了。
和 MVC 一样,它同样也是将业务分为三层:
Model 就不用说了,原来咋写还咋写。
public class WeatherModelImpl implements IWeatherModel {
@Override
public void getWeather(String cityName, final OnWeatherListener listener) {
String requestUrl = "https://free-api.heweather.com/s6/weather/now?location=" + cityName + "&key=5d520eb089e646acb********7e387";
OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder().url(requestUrl).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
listener.getWeatherError(e.toString());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String responseJson = response.body().string();
Gson gson = new Gson();
WeatherBean weatherArr = gson.fromJson(responseJson, WeatherBean.class);
String status = weatherArr.getHeWeather6().get(0).getStatus();
if ("ok".equals(status)) {
listener.getWeatherSuccess(weatherArr.getHeWeather6().get(0).getBasic().getLocation() + " 的天气是 " + weatherArr.getHeWeather6().get(0).getNow().getCond_txt());
} else {
listener.getWeatherError("查询出错:" + status);
}
}
}
});
}
}
View 层上面说过了,是将 Activity/Fragment 作为 View 层,并且新增了 View 接口,来和 Presenter 进行互动。
这个接口是干啥的呢?通俗点儿说就是,你这个页面需要干啥,你就得在这个接口中定义啥。例如你需要在页面当中显示一个 dialog,你就得定一个 showDailog 方法,同时也需要一个 dismissDailog 方法,你需要显示动画,自然也就需要一个 startAnimator 和 stopAnimator 方法了。这个根据你的页面功能自己去定义。
多说无益,上代码,还是 MVC 当中那个获取天气的例子。
View Interface:
public interface IWeatherView {
void showWeather(String result);
void showError(String error);
}
View
public class MainActivity extends AppCompatActivity implements View.OnClickListener, IWeatherView {
private Button btnSearch;
private TextView textWeather;
private EditText editCity;
private WeatherPrecenter precenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
precenter = new WeatherPrecenter(this);
btnSearch = findViewById(R.id.btn_search);
textWeather = findViewById(R.id.text_weather);
editCity = findViewById(R.id.edit_city);
btnSearch.setOnClickListener(this);
}
@Override
public void onClick(View v) {
precenter.search(editCity.getText().toString());
}
@Override
public void showWeather(String result) {
Message msg = new Message();
msg.obj = result;
handler.sendMessage(msg);
}
@Override
public void showError(String error) {
Message msg = new Message();
msg.obj = error;
handler.sendMessage(msg);
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
textWeather.setText((String) msg.obj);
}
};
}
在 MVP 模式当中,我们将 Activity/Fragment 作为 View,然后通过一个接口和外接发生交互。
Precenter 层
public class WeatherPrecenter implements OnWeatherListener {
private IWeatherView view;
private WeatherModelImpl model;
public WeatherPrecenter(IWeatherView view) {
this.view = view;
model = new WeatherModelImpl();
}
public void search(String cityName) {
model.getWeather(cityName, this);
}
@Override
public void getWeatherSuccess(String result) {
view.showWeather(result);
}
@Override
public void getWeatherError(String result) {
view.showError(result);
}
}
监听器
public interface OnWeatherListener {
void getWeatherSuccess(String result);
void getWeatherError(String result);
}
其实不管是 MVC 还是 MVP,都是将我们的页面分为几层,相互解耦,然后每层各司其职。
在 MVC 当中 Activity/Fragment 作为 Controller 来控制 Model 和 View 之间的交互。
在 MVP 当中,Activity/Fragment 作为 View 层,并且提供了一个对外的接口,View 层通过该接口和外接进行交互,而另外设置一个 Precenter 角色,用来主持 Model 和 View 之间的交互。
这样做的好处在于 View 层更加独立出来,它不用再去和 Model 层产生交互,Model 层只专注业务处理,View 层只专注接受/显示数据,他们两层之间的交互交由 Precenter 去处理。
缺点自然就是接口类爆发,会增长开发时间。