带有交互者和存储库的Android MVP架构扩展
原文链接:https://blog.mindorks.com/android-mvp-architecture-extension-with-interactors-and-repositories-bd4b51972339
目前机翻,待修正。
探索导致多样性。
进化是自然的真理,新的发展是由自然选择引导的。这导致许多不同的物种具有许多相似之处,并且它们的栖息地都适应性最好。一个人比另一个人好的观念只在有条件的情况下才有效,其中一个人更适合生存。当条件改变时,这个概念也是如此。对于任何软件设计也是如此。一种解决方案在其自身范围内优于另一种解决方案。
不久之后,我写了一系列关于Android MVP架构设计的文章。该项目在社区中受到好评,数百家公司和开发人员在其应用程序中添加了该体系结构。我们Mindorks也为我们的Android应用程序Correctify实现了相同的架构。随着这种架构暴露于许多用例,一些增强功能被确定为适合这些特定条件。
让我来描述一下Correctify。它是一个使用机器学习模型的英语拼写和语法编辑应用程序。它还提供测验和有趣的事实来学习和享受英语,通过竞赛帮助我们找到我们在世界上的排名。我们正在与开发人员一起成功管理上述架构的Correctify app构建。这个架构也导致了一个2.33 MB的小apk。这篇文章描述了如何实现这样的规模:文章的链接
因此,正如我所提到的,已经确定了一些增强功能可以更好地适应某些情况。所有这些情况都出现在具有巨大代码库的Android应用程序中,许多开发人员同时处理该项目。
在这些条件中确定的限制是两个:
- DataManager的集中化:MVP架构中的DataManager旨在将所有职责委托给ApiHelper,DbHelper和PreferenceHelper。对于大多数用例来说,这是一个很好的设计,因为它可以拦截Helper调用并执行一些预处理。但是,对于大型项目,这个类往往变得非常大。
- DbHelper的集中化:DbHelper旨在使用DAO类从数据库中获取数据。这对于大多数具有较少数据库查询的项目也是有利的,但对于大型项目而言往往变得非常大。
可以通过将Helper实例暴露给演示者来解决可能的DataManager集中问题。这将删除DataManager委托调用,因此会将代码库减少到需要交叉Helpers调用或对Helper进行一系列调用的少数方法。我会向当前的MVP架构推荐这个解决方案。
挖掘未绑定的潜力需要在我们到达目的地后提前两步。
现在,我提出对现有MVP架构进行一些根本性的更改,使其适用于非常大的项目,许多开发人员同时处理它。首先,让我们确定这些项目面临的挑战。
- 大型项目具有许多功能并且要管理这些功能,它需要具有模块化代码库。即使在模块中,最好的方法是隔离代码,以便封装所有功能,这意味着该功能的所有依赖关系最多都可以在其包中解析。
- 对于许多开发人员来说,在同一个项目上工作并避免代码与每个pull请求合并,我们需要进行功能封装。
让我们看看我们如何扩展当前的MVP项目以包含功能封装。
当前项目具有以下结构:
- DataManager有ApiHelper,DbHelper和PreferenceHelper。
- Presenter获取DataManager单例实例,DataManager委托所有Helper调用。
- 视图附带其Presenter。
在您继续前进之前,我建议您阅读原始的MVP架构文章:
功能封装的建议更改是DataManager和DbHelper的分散。
DataManager分散导致我们将其称为Interactor的结构。和DbHelper分散导致存储库。
- Interactor:每个Presenter都有自己的Interactor实例来代替单个DataManager。交互器负责与DataManager相同的职责,但它只关注它所服务的功能所需的那些数据访问和处理调用。
- 存储库:DbHelper被分解为存储库。例如,User表的所有数据库查询都是通过UserRepository而不是DbHelper完成的。UserRepository与DbHelper类似,通过UserDao进行所有相关查询。一个重要的区别是Repository是一个按需实例化,每个Interactor都获得一个与单例DbHelper相对的新Repository实例。
让我们看看这些新组件的架构蓝图:
将其与原始MVP架构蓝图进行比较:Image Link
我们可以看到DataManager和DbHelper被Interactors和Repositories取代,它们可以为每个Presenter单独使用。
MVP架构的重要变化:
- MvpInteractor:它是一个接口,列出了所有应用程序组件通用的数据访问API以及单例ApiHelper和PreferencesHelper的访问方法。
public interface MvpInteractor { ApiHelper getApiHelper(); PreferencesHelper getPreferencesHelper(); void setUserAsLoggedOut(); void setAccessToken(String accessToken); ... }
- BaseInteractor:它实现了MvpInteractor。所有后续的Interactors都扩展了这个BaseInteractor。BaseInteractor获取单例ApiHelper和PreferenceHelper。
公共类 BaseInteractor 实现 MvpInteractor { private final PreferencesHelper mPreferencesHelper ; 私人决赛 ApiHelper mApiHelper ; @Inject public BaseInteractor(PreferencesHelper preferencesHelper, ApiHelper apiHelper){ mPreferencesHelper = preferencesHelper; mApiHelper = apiHelper; } @覆盖公共 ApiHelper getApiHelper(){ 返回mApiHelper ; } @Override public PreferencesHelper getPreferencesHelper(){ return mPreferencesHelper ; } @Override public void setAccessToken(String accessToken){ getPreferencesHelper()。setAccessToken(accessToken); 。getApiHelper()getApiHeader() .getProtectedApiHeader() .setAccessToken(的accessToken); }
... }
- 组件方式Interactors扩展了BaseInteractor并实现了扩展MvpInteractor的接口,该接口在其中添加了自己的API。示例:LoginMvpInteractor扩展MvpInteractor并添加doServerLoginApiCall,doGoogleLoginApiCall和doFacebookLoginApiCall。类似地,LoginInteractor扩展BaseInteractor并实现LoginMvpInteractor。
示例:LoginMvpInteractor
公共接口 LoginMvpInteractor 扩展了 MvpInteractor { Observable <LoginResponse> doServerLoginApiCall( LoginRequest.ServerLoginRequest request); Observable <LoginResponse> doGoogleLoginApiCall( LoginRequest.GoogleLoginRequest request); Observable <LoginResponse> doFacebookLoginApiCall( LoginRequest.FacebookLoginRequest request); }
它由LoginInteractor实现。请注意,此Interactor提供了UserRepository的新实例。
公共类 LoginInteractor 扩展 BaseInteractor 实现 LoginMvpInteractor { private UserRepository mUserRepository ; @Inject public LoginInteractor(PreferencesHelper preferencesHelper, ApiHelper apiHelper, UserRepository userRepository){ super(preferencesHelper,apiHelper); mUserRepository = userRepository; } @覆盖公共可观察<LoginResponse> doServerLoginApiCall( LoginRequest.ServerLoginRequest请求){ 返回 。getApiHelper()doServerLoginApiCall(请求); }
... }
- Presenter与原始MVP架构具有相同的结构,唯一的区别是DataManager被组件的交互器取代。示例:LoginMvpPresenter接口。请注意在定义中添加了Interactor和View。
@PerActivity 公共接口 LoginMvpPresenter <V 扩展 LoginMvpView, 我扩展了 LoginMvpInteractor> extends MvpPresenter <V,I> { void onServerLoginClick(String email,String password); void onGoogleLoginClick(); void onFacebookLoginClick(); }
它由LoginPresenter实现:
公共类 LoginPresenter <V 扩展 LoginMvpView,我扩展了 LoginMvpInteractor> extends BasePresenter <V,I> 实现 LoginMvpPresenter <V,I> { private static final String TAG = “LoginPresenter” ; @Inject public LoginPresenter(I mvpInteractor, SchedulerProvider schedulerProvider, CompositeDisposable compositeDisposable){ super(mvpInteractor,schedulerProvider,compositeDisposable); }
... }
- 为每个Db表包装器Object创建存储库。此项目中的DAO由greenDAO库生成。
示例UserRepository:
public class UserRepository { private final DaoSession mDaoSession ; @Inject public UserRepository(DaoSession daoSession){ mDaoSession = daoSession; } 公共可观察<龙> insertUser(最终用户的用户){ 返回观察到。fromCallable(new Callable <Long>(){ @ Override public Long call()throws Exception { return mDaoSession .getUserDao()。insert(user); } }); } ... }
新项目结构:
将其与原始MVP项目结构进行比较:Image Link
您可以观察到登录功能组件独立于其他应用程序组件,并且已封装所有依赖项。任何使用登录功能的开发人员都可以独立工作到处理不同功能的其他开发人员。
你不需要原子弹来杀死蚂蚁。
这些组件使架构更具可扩展性和灵活性,但代价是更多工作。我必须再次重复原始MVP架构适用于大多数具有相当复杂性的项目,这个扩展版本适用于具有数百个功能的大型项目,并且许多开发人员同时处理它。我们在Correctify的代码库中非常愉快地使用原始架构。
注意:
ApiHelper和PreferenceHelper没有分成几部分,因为Android应用程序对它们的依赖性非常有限。
下面提供了使用Interactor和Repository扩展的MVP示例应用程序项目的链接:
此外,让我们成为朋友的Twitter,LinkedIn,Github上,和Facebook的。
学习是一段旅程,让我们一起学习!