MVP设计模式浅析、实战
来源:互联网 发布:python与量化投资 编辑:程序博客网 时间:2024/05/16 01:04
这篇文章介绍Android开发中MVP的概念以及实战MVP实例
MVP模式简介
- View 对应于Activity,负责View的绘制以及与用户交互;
- Model 依然是业务逻辑和实体模型;
- Presenter 负责完成View于Model间的交互
图例,其实很简单,Presenter起到了连接View和Model的任务,这样我们的Activity就不会再处理业务相关的繁琐代码。
那么MVP的关键也就是如何让Presenter层来完成View和Model之间的交互。
接下来我们就从具体的实际案例中来深入学习MVP模式的设计和编码。
案例很简单,我们就实现了一个列表:
- 加载数据前显示模拟loading的Toast;
- 模拟方法子线程加载数据;
- 加载数据完成隐藏loading,将数据显示在列表中。
项目目录结构
结构很清晰,我对View层和Presenter层都做了一个基类的抽象,来降低我们代码的耦合度。
View层
BaseView
public interface BaseView { void showLoading(); void hideLoading();}
这里只抽象了两个常用的试图操作的方法,你可以在这里增加更多的View操作的方法,比如showToast之类。
GirlView
public interface GirlView extends BaseView{ void setListItem(List<GirlEntity> data); void showMessage(String message);}
继承了BaseView,不仅持有了BaseView里面的view操作方法,同时新增了自己列表页面的View方法,显示列表数据,以及点击Item显示Message信息。
Presenter
BasePresenter
public class BasePresenter<T> { public T mView; public void attachView(T view){ this.mView = view; } public void dettach(){ mView = null; }}
这里在Presenter的基类里面我们使用了一个泛型T,因为我们不知道具体的Presenter层里面持有的到底是哪一个View,因此我们使用泛型来解决BasePresenter对View的持有。同时我们在BasePresenter中提供了两个方法,attacheView(View v)用来绑定Presenter和View,dettach()用来解绑Presenter和View层关系,这样我们可以实现有效的资源释放,避免出现OOM。
GirlPresenter
public class GirlPresenter extends BasePresenter<GirlView>{ private Handler mHandler; public GirlPresenter() { mHandler = new Handler(Looper.getMainLooper()); } public void getGirls(){ mView.showLoading(); final List<GirlEntity> list = new ArrayList<>(); new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(3*1000); for (int i=0; i < 10; i++){ GirlEntity girlEntity = new GirlEntity(); girlEntity.name = "赵丽颖"+i; girlEntity.imgRes = R.drawable.img; list.add(girlEntity); } mHandler.post(new Runnable() { @Override public void run() { mView.hideLoading(); mView.setListItem(list); } }); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); }}
这里我继承了BasePresenter,同时指定GirlPresenter持有了GirlView。然后我在GirlPresenter中实现了获取,绑定数据到View的操作,也就是实现了Model层和View层的交互。其实代码并不复杂,我才开始数据加载前用View层显示了loading,然后我在子线程处理了业务数据,处理完数据后我又切换至主线程完成了View层隐藏loading和数据显示。
Activity
Activity层主要是用来View层方法的实现以及Presenter层方法的初始化。
这里我同样抽象一个BaseActivity出来。
BaseActivity
public abstract class BaseActivity<V,T extends BasePresenter<V>> extends AppCompatActivity{ public T presenter; /** * 根据不同页面实现自己的P层 * @return */ public abstract T createPresenter(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); presenter = createPresenter(); //取的关联 presenter.attachView((V)this); } @Override protected void onDestroy() { super.onDestroy(); presenter.dettach(); }}
同样,我在BaseActivity中用泛型定义了一个Presenter,因为我们不确定具体的某一个Activity中究竟需要哪个Presenter。因为Presenter持有View的泛型对象,因此这里需要使用双层泛型的方法实现。然后我通过一个静态方法createPresenter()巧妙的实现了具体Activity中具体Presenter的初始化。之后我将Presenter跟View的处理关系同Activity的生命周期关联,这样就完美的实现了绑定和解绑操作。
GirActivity
接下来就是我们具体的某一个Activity里的操作了。
public class GirlActivity extends BaseActivity<GirlView,GirlPresenter> implements GirlView{ private ListView mListView; @Override public GirlPresenter createPresenter() { return new GirlPresenter(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(R.id.listview); presenter.getGirls(); } @Override public void showLoading() { Toast.makeText(this,"加载数据中...",Toast.LENGTH_SHORT).show(); } @Override public void hideLoading() { Toast.makeText(this,"数据加载完成...",Toast.LENGTH_SHORT).show(); } @Override public void setListItem(List<GirlEntity> data) { GirlAdapter adapter = new GirlAdapter(data,this); mListView.setAdapter(adapter); } @Override public void showMessage(String message) { }}
我们可以看到,Activity中的代码很简单也很清晰,我们初始化了GirlPresenter,这样GirlPresenter和GirlView就产生了关联,通过调用GirlPresenter中getGirls()方法,我们就可以获取列表数据,同时将View的操作回调到我们Activity实现的GirlView的方法中。
至此,MVP的使用就结束了。可能代码中涉及到一些基类的抽象,使得我们对MVP模式的理解略显复杂。但抽象是为了使我们简化代码,降低耦合度,相信这个工作是必须要做的。因此,建议大家自己动手,可以先不做抽象,单纯对某一个Activity进行某一个特定Presenter的实例化,让特定的Presenter持有特定的View,这样更方便大家的理解。当然理解完还是建议大家根据自己的理解和需要,对View和Presenter进行抽象,再对Activity进行抽象,这样就可以将MVP模式完美的应用到我们的项目中了。
如果对你有帮助,欢迎大家留言讨论,点赞关注!
- MVP设计模式浅析、实战
- 浅析MVP设计模式
- Android MVP设计模式浅析
- MVP 设计模式理解,实战理解MVP
- MVP 设计模式理解,实战理解MVP
- MVC、MVVM、MVP 框架设计模式浅析
- MVP-Android设计模式:下载器实战
- 浅析MVP模式
- Android MVP模式实战
- Android MVP模式实战
- Okhttp3网络请求框架+MVP设计模式简单实战
- MVC、MVP、MVVM模式浅析
- 浅析android的mvp模式
- 设计模式——Android 常用设计模式之MVP详解及项目实战
- MVP设计模式-1
- MVP设计模式
- MVP设计模式思路
- Android MVP 设计模式
- Delphi学习笔记(二)之类型转换
- 二叉树的层序遍历
- Java中动态绑定与Try finally中有return的理解
- iOS 单例设计模式
- linux curses库下子窗口实现行选择的功能
- MVP设计模式浅析、实战
- Xcode 导入voiceConvert /lib/libopencore-amrnb.a(wrapper.o)' does not contain bitcode. You must rebuild
- C++类和对象知识点整理七----虚基类和虚继承
- java与json的互相转换以及json字符串
- C++之线程池的原理及创建
- 分享七天轻松拿到公众号原创+赞赏
- Android 仿微信语音聊天音量大小显示控件
- Ajax的Json操作
- html css3不拉伸图片显示效果,类似淘宝的