听到很多人在讨论MVVM,我自己早些时候也写过一篇介绍MVVM的文章(玩转Android之MVVM开发模式实战,炫酷的DataBinding! ),实际上,在Android开发领域中,除了MVVM之外,MVP也是一个非常好用的开发模式。至于什么是MVC、什么是MVP什么是MVVM应该不用我说了吧,本文我主要是想通过一个案例来带小伙伴们看看如何在我们的项目中使用MVP。关于MVP的太多的理论知识小伙伴们自行搜索。
OK,我们先来看看项目效果图:
就这样一个东东,直接写当然很简单,一个Activity中放一个ListView,那么今天我们来看看用MVP的方式怎么实现这样的效果。OK,首先来看看项目结构:
数据全部由Model包中的类和方法提供,视图的现实全部由view包中的控件实现,view包中的控件和model中的数据不直接接触,全部通过presenter来实现两者之间的组合。OK,整体思路就是这样,我们先来看看model中的数据提供类吧:
ILoadFoodData.java:
public interface ILoadFoodData {
public void getData(String httpUrl,OnDataLoadListener onDataLoadListener);
}
就一个功能,获取数据,第一个参数是数据地址,第二个参数是获取数据的监听器,OK,那我们再来看看这个接口的实现类:
public class LoadFoodDataImpl implements ILoadFoodData {
public void getData(String httpUrl, final OnDataLoadListener onDataLoadListener) {
final Request request = new Request.Builder()
.url(httpUrl)
.build();
Call call = OkHttpUtil.getOkHttpClient().newCall(request);
call.enqueue(new Callback() {
public void onFailure(Call call, IOException e) {
onDataLoadListener.onFailed(e.getMessage());
}
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
onDataLoadListener.onSuccess(JsonParse.parseJson2FoodList(response.body().string()));
} else {
onDataLoadListener.onFailed("数据加载失败");
}
}
});
}
}
数据下载成功之后先把数据转化为集合,然后调用OnDataLoadListener中相应的方法即可。OK,那我们再来看看OnDataLoadListener:
public interface OnDataLoadListener {
public void onSuccess(List<FoodEntity> foodEntities);
public void onFailed(String errorMsg);
}
至于其他的数据下载类等我这里就不贴出来了,小伙伴们可以直接文末下载源码阅读。
OK,这里就是我们的数据提供类,接下来看看View,将Activity需要实现的功能抽象成相应的接口,我这里设置了如下一些功能:
public interface IFoodView {
//显示加载进度条
public void showLoading();
//隐藏加载进度条
public void hideLoading();
//给ListView设置数据源
public void initData(MyAdapter adapter);
//显示错误信息
public void showErrorMsg(String errorMsg);
}
OK,那我们来看看我们的Activity是什么样子:
public class MainActivity extends AppCompatActivity implements IFoodView {
private ListView lv;
private FoodPresenter presenter = new FoodPresenter(this);
private ProgressBar pb;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
presenter.loadData();
}
private void initView() {
lv = (ListView) findViewById(R.id.lv);
pb = ((ProgressBar) findViewById(R.id.pb));
}
public void showLoading() {
pb.setVisibility(View.VISIBLE);
}
public void hideLoading() {
pb.setVisibility(View.GONE);
}
public void initData(MyAdapter adapter) {
lv.setAdapter(adapter);
}
public void showErrorMsg(String errorMsg) {
Toast.makeText(this, errorMsg, Toast.LENGTH_SHORT).show();
}
}
这里的代码都很简单,不用多说,这里小伙伴们需要牢记的就是View类中不要直接和Model中的数据进行对接就好,所有的对接都放在Presenter中:
public class FoodPresenter {
private IFoodView iFoodView;
private ILoadFoodData iLoadFoodData;
private Context context;
private Handler mHandler = new Handler();
public FoodPresenter(IFoodView iFoodView) {
this.iFoodView = iFoodView;
this.context = (Context) iFoodView;
iLoadFoodData = new LoadFoodDataImpl();
}
public void loadData() {
iFoodView.showLoading();
iLoadFoodData.getData(Constant.LISTURL, new OnDataLoadListener() {
//小伙伴们注意这个方法是在子线程中回调的,现在要在主线程中更新UI
public void onSuccess(final List<FoodEntity> foodEntities) {
mHandler.post(new Runnable() {
public void run() {
iFoodView.initData(new MyAdapter(foodEntities,context));
iFoodView.hideLoading();
}
});
}
public void onFailed(final String errorMsg) {
mHandler.post(new Runnable() {
public void run() {
iFoodView.showErrorMsg(errorMsg);
iFoodView.hideLoading();
}
});
}
});
}
}
如上代码,在presenter中将数据和View再组合到一起。
OK,就这样一个小小的案例,希望小伙伴能够借此一窥MVP这种开发模式。如果大家对MVP这种开发模式的理论还有什么疑问的话,欢迎留言讨论。
源码下载https://github.com/lenve/HealthyFoodMVP
以上。