https://www.jianshu.com/p/4736ebe1114bgit
鸿洋大神写的,MVP模式的基础介绍github
传统MVP的弊端:数据库
MVP须要建立太多的类和接口,而且每次通讯都须要繁琐的经过接口传递信息缓存
软解决,那就要动动脑子,稍微优雅的解决了网络
对于逻辑简单的页面能够不使用Presenter,直接在Activity或Fragment中处理逻辑,在Presenter中若是不须要处理数据,也能够不使用Model架构
Presenter和Model均可以无限制的重用,因此MVP的划分不须要太细粒度,稍微粗粒度一点,即不须要每一个Activity或Fragment都给他划分一套MVP,能够几个Activity或Fragment使用同一个Presenter(使用同一个类不是同一个对象,这个Presenter含有能够共用的逻辑),也可一个Activity或Fragment根据不一样的需求持有多个不一样类型的Presenter对象,Model层同理,这样灵活使用,能够在必定程度上缓解MVP类和接口较多的缺点app
经过上面的解决方案,是能够必定的缓解MVP的缺点,可是并不能彻底解决上述缺点框架
好比想重用Presenter,Presenter就必须只含有公用的逻辑,而实际项目中公用的逻辑并非那么多,因此能减小的类和接口也是颇有限的,若是强制将不一样页面的逻辑放在同一个Prsenter中,来达到重用的目的,那么每一个Activity会被迫实现许多并不须要的方法,得不偿失异步
1.粒度很差控制,控制很差就须要写过多的类和接口 2.如要重用presenter可能会实现过多不须要的接口 3.Presenter和View经过接口通讯太繁琐,一旦View层须要的数据变化,那么对应的接口就须要更改
写mvp的时候,presenter会持有view,若是presenter有后台异步的长时间的动做,好比网络请求,这时若是返回退出了Activity,后台异步的动做不会当即中止,这里就会有内存泄漏的隐患,因此会在presenter中加入一个销毁view的方法
通用的presenter来为咱们添加view的绑定与销毁
//presenter中添加mvpView 置为null的方法 public void onDestroy(){ mvpView = null; } //退出时销毁持有Activity @Override protected void onDestroy() { mvpPresenter.onDestroy(); super.onDestroy(); }
界面须要提供的UI方法中会有不少相似的UI方法,能够把它们提取到一个公共的父类接口中。好比提取显示loading界面和隐藏loading界面的方法,其余的view层接口就能够直接继承BaseView接口,没必要重复的写显示和隐藏loading界面方法。
presenter绑定到activity和View的绑定和解绑操做是每一个Activity都会去作的,一样这里我也但愿能有一个父类来完成这个统一的操做。
构建一个对象有时候还要构建一堆其余的对象,而且其余对象的构建一样复杂,而且必须按顺序构建,并且须要的对象的生命周期都不同,有些生命周期可能和Activity同样,有些多是单例,因此在构建的时候还要考虑对象声明周期,考虑对象的来源
这个时候依赖注入框架就派上用场了,咱们只用专一于怎么实现功能,对象的依赖关系和生命周期,都让它来帮咱们管理,一个Inject,它会按照依赖关系帮咱们注入咱们须要的对象,而且它会管理好每一个对象的生命周期,在生命周期还没结束的状况下是不会重复new的
以前我看了几个使用MVP+Dagger+Retrofit开发,而且有必定star量的开源项目,因此对比了下个人框架,有如下几点:
使用Dagger的场景太少了,大部分只是使用Dagger注入MVP类,而且有些Retrofit都是本身new,并无使用Dagger管理,甚至有些使用一次接口就retrofit.create(ApiService.class)一次,这个本可使用Dagger将它做为单例来调用的
有一些设计的Component和Module彻底只是用来注入Activity和一些单例
@ActivityScope @Component(modules = {ActivityModule.class},dependencies = {AppComponent.class}) public interface ActivityComponent { void inject(AActivity activity); void inject(BActivity activity); void inject(CActivity activity); ... }
仍是和第2条有关,若是只有一个Module,Dagger
就没法根据每一个Presenter的须要,提供多个不一样的Model,好比这个Presenter使用过这个接口,而且缓存已经在Model中写好,其余Presenter若是也要用到这个接口,就能够直接重用这个Model,MVP最大的好处之一就是能够重用M和P层
有些没有Model层,直接给Presenter注入Retrofit Api(有些是注入一个管理类,若是项目小接口少,这样还不错,可是有没有想过项目一大,接口一多里面就很是混乱),全部网络请求逻辑在Presenter中,若是如今需求变了,须要加入缓存,就须要更改Presenter的逻辑,这样就可能影响一些和这个功能无关的逻辑,若是有Model层,里面持有请求网络和缓存的功能类,这样Presenter就不须要管,数据是从网络仍是数据库获取的,Model层只用保证返回给Presenter的数据无误,而Presenter只用专一于逻辑,这样各自只用保证各自的职责,屏蔽细节,易扩展,出错也好定位
这里根据Google
官方的MVP项目,能够在Contract中定义MVP的接口,便于管理,此框架无需定义Presenter接口,因此Contract只定义Model和View的接口
通常让 Activity 或 Fragment 实现 Contract 中定义的 View 接口,供 Presenter 调用对应方法操做 UI , BaseActivity 默认注入 Presenter ,如想使用 Presenter ,必须指定 Presenter 的范型(虽然只能够指定一个范型,可是能够自行生成并持有多个 Presenter ,达到重用的目的),和实现setupActivityComponent 来提供 Presenter 须要的 Component 和 Module(如这个页面逻辑简单并不须要 Presenter ,那就不指定范型,也不实现方法)
Model 实现 Contract 的 Model 接口,而且继承 BaseModel ,而后经过 IRepositoryManager 拿到须要的 Service 和 Cache 为 Presenter 提供须要的数据(是否使用缓存请自行选择)
Presenter在MVP中的大部分的做用为经过从Model层接口获取数据,在调用View层接口显示数据,首先实现BasePresenter,指定Model和View的范型,注意必定要指定Contract中定义的接口,Presenter须要的Model和View,都使用Dagger2注入,这样即解藕又方便测试,怎么注入?
这里的Module提供当前业务逻辑对应的View和Model接口(Contract中定义的接口)的实现类,Model须要AppComponent中提供的RepositoryManager来实现网络请求和缓存,因此须要经过Component依赖AppComponent来拿到这个对象
在上面的代码中 ActivityScope 大量出如今 Module 和 Component 中,Dagger2 使用 Scope 限制每一个 Module 中提供的对象的生命周期, Dagger2 默认只提供一个 @Singleton
Scope 即单例,本框架提供 @ActvityScope 和 @FragmentScope ,若有其余需求请自行实现, Module 和 Component 定义相同的 Scope 后 Module 中提供的对象的生命周期会和 Component 的生命周期相绑定(即在 Component 生命周期内,如需屡次使用到 Moudle 中提供的对象,但只会调用一次@Provide 注解的方法获得此对象)
Application生命周期是和App是同样的,因此适合提供一些单例对象,本框架使用Dagger2
管理,使用AppComponent来提供全局全部的单例对象,因此须要自定义一个Application继承自BaseApplication,便可在App的任何地方,经过BaseApplication的getAppComponent()方法,拿到AppComponent里面声明的全部单例对象
RepositoryManager 用来管理网络请求层,以及数据库请求层
AppManager用于管理全部的Activity,内部持有一个含有全部存活的Activity(未调用onDestroy)的List,和一个当前在最前端的Activity(未调用onPause),AppManager封装有多种方法,能够很方便的对它们进行操做,也能够在未持有AppManager的状况下,经过EventBus
远程遥控它的全部方法,这样咱们能够在整个app的任何地方对任何Activity进行全局操做,好比在app请求网络超时时让最前端的Activity显示链接超时的交互页面(这个逻辑不用写到当前请求的Activity里,能够在一个单例类里作全局的统一操做,由于能够随时经过AppManager拿到当前的Activity)
在任意位置关闭全部的activity,得到在前台的activity作一些操做,判断某个activity实例是否存活
Application继承activityLifeCycle管理生命周期
oncreate时:
activity加入appmanager
注入Dagger单例
onresume时:
设定当前的前台activity
onDestroy时:
移除全部的activity
ClientModule:
提供retrofit,okhttp,database单例
AppModuel:
提供application,RepositoryManager单例
设置mainContentView
绑定butterKnife
设定toolbar