项目地址:https://github.com/coolstar1204/MakePoster
MVP的学习使用
- 什么是MVP
- 我的项目哪里是MVP
- MVP的优点
- MVP的不足
什么是MVP
MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模式,MVP与MVC有着一个重大的区别:在MVP中View并不直接使用Model,它们之间的通信是通过Presenter (MVC中的Controller)来进行的,所有的交互都发生在Presenter内部,而在MVC中View会直接从Model中读取数据而不是通过 Controller。
上面这段是从百科引用而来的,我的个人理解最深的就是,Model不与View交互是其与MVC的最大区别和特点。具体到我的开发中,我为了学习这个模式,在第一个选择图片界面中,我让请求相册数据库时,使用Model层对象进行异步的数据库访问及图片对象列表的创建,然后通过EventBus通知时,只通知到Presenter对象上,而不是直接通知到Activity或Fragment上,这样方便界面调整。
public interface IMain {
void asyncLoadPictureList(Context context);
}
public void asyncLoadPictureList(final Context context) {
ThreadBuilder.getInstance().runThread(new Runnable() {
@Override
public void run() {
String[] projection = new String[] { MediaStore.Images.Media._ID,
MediaStore.Images.Media.BUCKET_ID,
MediaStore.Images.Media.BUCKET_DISPLAY_NAME,
MediaStore.Images.Media.DISPLAY_NAME, // 图片文件名
MediaStore.Images.Media.DATA // 图片绝对路径
};
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
try {
Cursor cursor = context.getContentResolver().query(uri,projection,null,null,null);
if(cursor!=null){
List<PictureInfo> list = new ArrayList<PictureInfo>();
while (cursor.moveToNext()){
PictureInfo item = new PictureInfo();
item.fileName = cursor.getString(4);
item.picName = cursor.getString(3);
item.dirName = cursor.getString(2);
if(BitmapUtils.isBigBitmap(item.fileName)){
list.add(item);
}
}
EventBus.getDefault().post(list);//使用EventBus进行回调通知
}else{
EventBus.getDefault().post(new AsyncErrorInfo(2,"parse error"));//使用EventBus进行回调通知
}
} catch (Exception e) {
e.printStackTrace();
EventBus.getDefault().post(new AsyncErrorInfo(1,"db query error"));//使用EventBus进行回调通知
}
}
});
}
这里直接使用EventBus进行异步回调更新,只不过在MVP的模式下,更新的地方不在Activity上,而是在
Presenter上。代码如下:
public MainPresenter(IMainView mainView) {
this.mainView = mainView;
this.mainMod = new MainMod();
EventBus.getDefault().register(this);
}
public void releasePresenter(){
EventBus.getDefault().unregister(this);
}
@Subscribe(threadMode = ThreadMode.MainThread)
public void onEventReceiveList(List<PictureInfo> list){
mainView.setPictureList(list);
mainView.stopLoading();
mainView.showPictureList();
}
在上面的代码中,mainView是一个接口变量,其保存的就是MVP中的View实现类,在本程序中,我是使用MainActivity实现了这个接口,来完成最后数据的加载显示的。这可以很方便以后界面从Activity转为Fragment等变更。
public interface IMainView {
public void startLoading();
public void stopLoading();
public void setPictureList(List<PictureInfo> list);
public void showPictureList();
public void showErrorInfo();
}
最后总结一下本例中主界面的MVP就是:
Activity或Fragment中创建一个Presenter的对象,同时把自己以接口实现类的方式,传入Presenter中成为其成员变量,方便Activity与Presenter的交互调用,在Presenter中,创建出对应的Model对象进行模型数据的管理,同时Presenter实现Model要求的回调,方便Model把更新返回给Presenter,Presenter在接到Model的更新数据回调后,就可以加上自己的业务规则或界面切换逻辑后,调用IMainView中的接口把内容显示到Activity或Fragment中,如此一来,Model就可以不用知道View长什么样了。View也不需要知道数据是怎么来的。
Activity/Fragment —->Presenter———>Model——–>Presenter——->Activity/Fragment