关于Android 的MVP的理解
来源:互联网 发布:实体转json忽略空值 编辑:程序博客网 时间:2024/05/07 06:01
现在主流都采用MVP的模式的搭建android的项目,包括连谷歌也在前段时间发布了几个关于mvp模式的写法,其中包括和rxjava和dragger2的融合的项目。所以是时候换一种方式写android的项目
写在前面的话
传统的mvc的模式,写android的项目,随着业务的扩展会使得c层(Activity)的代码变得臃肿和难以维护,如果你只是为了将原先的属于的c层的代码移除到p层,那么只是换汤不换药,只不过原来臃肿的代码换到了p层。所以在之前,我们一定要明白,分层的概念。 关于android的分层的概念其实就是低耦合的具体的表现。
参考:
1. Android项目重构之路:架构篇
2. Android项目重构之路:界面篇
3. Android项目重构之路:实现篇
mvp的模式
最简单的模型图
View: 负责加载视图,更新视图和隐藏视图,总之View管理着视图的所有操作。
Presenter:负责事的逻辑处理,并且根据处理的结果去更新View层和保存Model层
Model:这里的model不是单一的bean的对象,其中包括了data和domain。下面的图表明了三者包涵部分以及协作关系。
针对每层具体的描述
这里以点击登录去登录的过程来分析。
View 层
这层属于整个体系最简单,主要就是用来负责视图操作的,当我们拿到设计需求的时候,就大概知道每个页面的大概会展示的时候会存在的操作,比如loadList(),showError(),loadProgess(),等一些操作。而将所有的视图的操作都给注入进来的presenter去操作。比如这个点击登录按钮,在监听的操作操作,交给presenter去处理。等待presenter的处理完结果的通知页面的操作即可。
另外现在的Data Binding 可以进一步简化View 的代码,关于这方面的学习可以
Data Binding 用户指南(Android)
Presenter
我把这层的想象成调控层,就是接受从View层的信息,从model层去model,然后通过callback的形式去监听model处理完逻辑后,从而通知更新视图和更新数据等。是一个集disaptcher和deliver的中间层。比如登录过程,它接受View传过来的点击事件,然后取到一个user,调用user.login()的方法,并通过监听的方式去得到成功和失败的结果。并根据结果去通知view的去改变视图。
这一块可以实用RxJava,和RxAndroid,从而解决回调嵌套回调的问题。
Model层
个人觉得是整个框架的最难的地方,第一其必须向上隐藏实现的过程和实现细节,第二向下能够满足业务的需求。其中包括大致分为DataManager和interactor两个部分。
DataManager:大致可以分为Local和remote,其中实现必要的添,删,改,查等操作。
其中Local 可以分为- DB: 用的最多- DisK : 一般采用LurDiskCache其中remote,通过api的方式得到数据- Retrofit- Volley- OkHttp
interactor
具体的逻辑操作,比如登录,user.login().
对于这一块可以采用工厂模式向上提供model,供presenter去操作。并添加相应的改,删,增的操作去保存数据。
项目的例子
CreateNewAndroid
项目的简单说明
项目就是做一个简单的splashActivity,用来展示splashImage的。接口是来自开源的知乎日报的。
其中SplashContract中声明了view和presenter的所有的方法。
public interface SplashContract { interface View { void displayImage(String imageUrl); void loading(); void showErrorMessage(String message); } interface Presenter { void requestImageUrl(); void attach(View view); }}
而在真正实现的类中用来都是用接口来接偶的。
真正实现的view层,只有视图的相关的操作。
public class SplashActivity extends AppCompatActivity implements SplashContract.View { private ImageView mSplashImage; private ProgressBar mLoadingBar; private SplashContract.Presenter mPresenter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_splash); mSplashImage = (ImageView) findViewById(R.id.iv_splash); mLoadingBar = (ProgressBar) findViewById(R.id.pb_splash_loading); mPresenter = new SplashPresenter.SplashPresenterFactory().newSplashPresenterInstance(); mPresenter.attach(this); mPresenter.requestImageUrl(); } @Override public void displayImage(String imageUrl) { mLoadingBar.setVisibility(View.GONE); mSplashImage.setVisibility(View.VISIBLE); Glide.with(this) .load(imageUrl) .asBitmap() .into(mSplashImage); } @Override public void loading() { mLoadingBar.setVisibility(View.VISIBLE); mSplashImage.setVisibility(View.GONE); } public void showErrorMessage(String message) { mSplashImage.setVisibility(View.GONE); mLoadingBar.setVisibility(View.GONE); Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); }}
真正的presenter层,采用rxjava和lambda表达式来写的,其中逻辑操作交给SplashImage去执行。SplashImage是一个抽象,对于presenter层来说,不需要做的SplashImage的具体实现类是什么,我们可以告诉其我们需要什么,通过SplashImageFactory来生成一个我们想要的一个SplashImage的对象。
public class SplashPresenter implements SplashContract.Presenter { private SplashContract.View splashView; private SplashImage splashImage; public SplashPresenter() { splashImage = new SplashImage.SplashImageFactory().newInstance(SplashImage.DISPLAY_SHOW_LOCAL_IF_HAVE); } @Override public void requestImageUrl() { splashImage.getSplashImageBean() .doOnSubscribe(() -> splashView.loading()) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe(imageBean -> { splashView.displayImage(imageBean.getImg()); splashImage.saveSplashImageBean(imageBean); } , throwable -> splashView.showErrorMessage(throwable.getMessage())); } @Override public void attach(SplashContract.View view) { splashView = view; } public static class SplashPresenterFactory { public SplashPresenter newSplashPresenterInstance() { return new SplashPresenter(); } }}
而Model层,方法有添,删,改,查等一系列操作,其中实现类RemotoSplashImage(借助Retrofit来实现)和LocalSplashImage(借助SharePreference来实现的),而具体提供什么的样SplashImage的是根据业务的需求来选择的,这里选择的是如果本地存在,就加载到本地,如果本地没有则加载网络的。
public interface SplashImage { int DISPLAY_ONLY_SHOW_NET = 0; int DISPLAY_SHOW_LOCAL_IF_HAVE = 1; Observable<SplashImageBean> getSplashImageBean(); Observable<Boolean> saveSplashImageBean(SplashImageBean bean); Observable<Boolean> deleteSplashImageBean(SplashImageBean bean); Observable<SplashImageBean> updateSplashImageBean(SplashImageBean bean); class SplashImageFactory { public SplashImageFactory() { } public SplashImage newInstance(int priority) { switch (priority) { case DISPLAY_SHOW_LOCAL_IF_HAVE: if(!TextUtils.isEmpty(SharePreferenceManager.getsPreferencesManager(NewAndroidApplication.getApplication()).getLocalSplashImageUrl())){ return new LocalSplashImage(); } default: case DISPLAY_ONLY_SHOW_NET: return new RemotoSplashImage(); } } }}
运行后结果显示
而且根据log的可以看到,确实是第一次加载过后保存在本地就没有请求网络。而是加载本地的
第一次进入的log
之后进入的log
详细项目见CreateNewAndroid。
如有改进和指错的地方还请大家指出来。谢谢大家
- 关于Android 的MVP的理解
- Android MVP 的理解
- 关于MVP的一些理解
- 关于android的设计模式---MVP的个人理解
- Android----MVP模式的理解
- Android MVP模式的理解
- Android MVP的一点理解
- 关于MVP+CLEAN 框架的理解
- android中MVP的理解和实例
- Android MVP设计的简单理解
- Android MVP设计模式的理解
- Android:聊聊我所理解的MVP
- Android中的MVP模式的理解
- 理解中Android的MVP开发模式~
- Android 谈谈我所理解的MVP
- MVC、MVP的理解
- MVP的简单理解
- MVP的简单理解
- Android ViewGroup事件分发机制
- 4并查集的合并与删除
- BZOJ 1150 [CTSC2007]数据备份Backup
- JS实现实时时间显示效果
- 事件CEvent的使用
- 关于Android 的MVP的理解
- 队列的C语言实现(循环数组结构)
- Git配置多个SHH Key
- 粒子系統模組Particle System Modules - FAQ
- acm最终总结
- [leetcode-327]Count of Range Sum(java)
- Java 引用 WeakReference
- webuploader
- 设计模式-策略设计模式