带有交互器和存储库的 Android MVP 架构扩展
自然的真理是进化,新的发展是由自然选择引导的。因此,有许多不同的物种有许多相似之处,它们都最能适应它们的环境。一种优于另一种的概念仅适用于一种更适合生存的有限情况。当情况发生变化时,概念也会发生变化。这对于任何软件设计都同样适用。就其本身而言,一个答案优于另一个。如前所述,为了更好地响应某些条件,我们发现了一些增强功能。所有这些场景都出现在具有大型代码库的 Android 应用程序和同时从事该项目的多个开发人员。
在这种情况下发现了两个限制:
- DataManager 集中化:在MVP 架构中,DataManager 旨在将所有职责外包给ApiHelper、DbHelper 和PreferenceHelper。对于大多数使用情况来说,这是一个出色的架构,因为它允许您拦截 Helper 调用并进行一些预处理。然而,对于大型项目,这个类可能会变得相当庞大。
- DbHelper 集中化:创建 DbHelper 是为了使用 DAO 类从数据库中获取数据。这对于大多数数据库查询较少的项目来说也是很好的,但对于大型项目来说它可能会变得非常庞大。
集中式 DataManager 的问题或许可以通过将 Helper 实例暴露给 Presenters 来解决。这将消除 DataManager 委托调用,将代码库减少到一些需要交叉 Helper 调用或一系列 Helper 调用的函数。这种方法非常适合现有的 MVP 设计。一旦我们达到我们的目标,挖掘未开发的潜力就需要向前迈进两步。我们现在对现有的 MVP 设计提出一些重大改进,以使其适用于许多开发人员同时进行的大型项目。让我们首先确定与此类举措相关的障碍。
大项目?别担心
大型项目包含许多功能,为了管理这些功能,需要一个模块化的代码库。即使在模块内部,理想的策略是将程序分开,以便封装所有功能,这意味着该功能的所有依赖项最多可以在其包中解决。为了让多个开发人员在同一个项目上进行协作,同时避免每个拉取请求合并代码,我们必须提供功能封装。
要了解Android MVP,请访问此处。
DataManage r 去中心化产生交互器结构,而 DbHelper 去中心化产生存储库。
- Interactor:每个Presenter 接收自己的Interactor 实例,而不是单独的DataManager。交互器与 DataManager 具有相同的职责,但它只关心它提供的功能所必需的数据访问和处理调用。
- DbHelper 被组织成存储库。例如,用户表的所有数据库查询都是通过 UserRepository 而不是 DbHelper 执行的。 UserRepository 与 DbHelper 一样,通过 UserDao 路由其所有查询。
GeekTip: In contrast to a singleton DbHelper, the Repository is instantiated on demand, and each Interactor receives a new Repository instance.
与最初的 MVP 架构蓝图相比,我们可以看到 DataManager 和 DbHelper 已被替换为 Interactors 和 Repositories,每个 Presenter 都可以单独使用它们。
MVP架构发生了重大变化
gfgMVPInterctor:它是一个接口,列出了所有应用程序组件共享的数据访问 API 以及 sampleAPIHelper 和 PreferencesHelper 单例的访问方法。
Java
public interface gfgMVPInteractor {
sampleAPIHelper getSampleAPIHelper();
PreferencesHelper gfgPrefrences();
void setUserAsLoggedOut();
// Logging out the user
void setAccessToken(String accessToken);
// Setting the user access token
// Further Code goers here
}
Java
public class BaseInteractor implements GFGMVPINTERCTOR {
private final PreferencesHelper GFGPREFERENCESHELPER;
private final ApiHelper mApiHelper;
@Inject
public BaseInteractor(PreferencesHelper preferencesHelper, ApiHelper SAMPLEAPIHELPER) {
GFGPREFERENCESHELPER = preferencesHelper;
mApiHelper = SAMPLEAPIHELPER;
}
@Override
public ApiHelper GETSAMPLEAPIHELPER() {
return mApiHelper;
}
@Override
public PreferencesHelper getPreferencesHelper() {
return GFGPREFERENCESHELPER;
}
@Override
public void setAccessToken(String GFGACCESSTOKEN) {
getPreferencesHelper().setAccessToken(GFGACCESSTOKEN);
GETSAMPLEAPIHELPER().getApiHeader()
.getProtectedApiHeader()
.setAccessToken(GFGACCESSTOKEN);
}
Java
public class GFGLOGININTERACTOR extends BaseInteractor
implements LoginMvpInteractor {
private UserRepository GFGUSERREPOSITORY;
@Inject
public GFGLOGININTERACTOR(PreferencesHelper preferencesHelper, ApiHelper SAMPLEAPIHELPER, UserRepository userRepository) {
super(preferencesHelper, SAMPLEAPIHELPER);
GFGUSERREPOSITORY = userRepository;
}
@Override
public Observable DOSERVICECALL(
LoginRequest.ServerLoginRequest request) {
return getApiHelper().DOSERVICECALL(request);
}
Java
public class GFGUSERREPOSITORY {
private final GFGDAOSESSION GFGGFGDAOSESSION;
@Inject
public GFGUSERREPOSITORY(GFGDAOSESSION GFGDAOSESSION) {
// A sample GFG DAO session
GFGGFGDAOSESSION = GFGDAOSESSION;
}
public Observable insertUser(final User user) {
return Observable.fromCallable(new Callable() {
@Override
// Ovverriding the method
public Long call() throws Exception {
// Just exceptional Handling
return GFGGFGDAOSESSION.getUserDao().insert(user);
}
});
}
// Your other code go here
}
gfgMVPInterctor由 BaseInteractor 实现。这个 BaseInteractor 被所有后续的 Interactor 扩展。 BaseInteractor 接收一个单例 ApiHelper 和一个单例 PreferenceHelper。
Java
public class BaseInteractor implements GFGMVPINTERCTOR {
private final PreferencesHelper GFGPREFERENCESHELPER;
private final ApiHelper mApiHelper;
@Inject
public BaseInteractor(PreferencesHelper preferencesHelper, ApiHelper SAMPLEAPIHELPER) {
GFGPREFERENCESHELPER = preferencesHelper;
mApiHelper = SAMPLEAPIHELPER;
}
@Override
public ApiHelper GETSAMPLEAPIHELPER() {
return mApiHelper;
}
@Override
public PreferencesHelper getPreferencesHelper() {
return GFGPREFERENCESHELPER;
}
@Override
public void setAccessToken(String GFGACCESSTOKEN) {
getPreferencesHelper().setAccessToken(GFGACCESSTOKEN);
GETSAMPLEAPIHELPER().getApiHeader()
.getProtectedApiHeader()
.setAccessToken(GFGACCESSTOKEN);
}
Component-wise Interactor 扩展了 BaseInteractor 并实现了一个接口,该接口扩展了 gfgMVPInterctor 并包括它自己的 API。示例:GfGMvpInteractor 是 MvpInteractor 的扩展,包括 doServiceCall、doGoogleLoginApiCall 和 doFacebookLoginApiCall。 GFGLoginInteractor 和 BaseInteractor 一样,扩展了 BaseInteractor 并实现了 GfGLoginMvpInteractor。
Java
public class GFGLOGININTERACTOR extends BaseInteractor
implements LoginMvpInteractor {
private UserRepository GFGUSERREPOSITORY;
@Inject
public GFGLOGININTERACTOR(PreferencesHelper preferencesHelper, ApiHelper SAMPLEAPIHELPER, UserRepository userRepository) {
super(preferencesHelper, SAMPLEAPIHELPER);
GFGUSERREPOSITORY = userRepository;
}
@Override
public Observable DOSERVICECALL(
LoginRequest.ServerLoginRequest request) {
return getApiHelper().DOSERVICECALL(request);
}
Presenter 的结构类似于原始 MVP 架构,不同之处在于 DataManager 被替换为组件的交互器。 GFGLoginMvpPresenter 是一个界面示例。在定义中,Interactor 已经包含在 View 旁边。
示例用户存储库
让我们看一个真实世界的用户仓库示例,以更好地理解整个概念:
Java
public class GFGUSERREPOSITORY {
private final GFGDAOSESSION GFGGFGDAOSESSION;
@Inject
public GFGUSERREPOSITORY(GFGDAOSESSION GFGDAOSESSION) {
// A sample GFG DAO session
GFGGFGDAOSESSION = GFGDAOSESSION;
}
public Observable insertUser(final User user) {
return Observable.fromCallable(new Callable() {
@Override
// Ovverriding the method
public Long call() throws Exception {
// Just exceptional Handling
return GFGGFGDAOSESSION.getUserDao().insert(user);
}
});
}
// Your other code go here
}
结论
您可以看到登录功能组件独立于程序的其余部分,并且包装了它们的所有依赖项。任何从事登录函数的开发人员都可以独立于从事其他项目的其他开发人员独立工作。
这些组件增加了体系结构的可扩展性和灵活性,尽管以额外的劳动力为代价。我必须强调,基本的 MVP 设计适用于大多数具有合理复杂性的项目,但这个扩展版本适用于具有数百个功能和几个人同时工作的非常大的项目。我们很高兴在我们的应用程序代码库中使用原始架构。