JessYanCoding / JessYanCoding/MVPArms

实际开发中对 MVP 使用上的优化

Open
#203 14 comments 11 reactions 0 assignees View on GitHub
enhancement
Dominant language
Java
Stars
10.2k
Forks
2.3k
PR merge metrics
No merged PRs in 30d

Description

在使用框架过程中碰到 mvp 架构需创建文件数量庞问题,可能我的做法不正确,特请教下如何优化?

希望大佬能增加 DEMO 功能,提供多功能下如何设计和组织代码,为大家提供参考。以下是我的一些设计疑问,也贴出了源码希望和大家一起探讨如何设计。

比如用户模块下有以下功能
- 登录
- 注册

由于两个页面的 UI 、逻辑、网络请求都不一样,所以普通的做法是单独为每个功能创建 XXXActivity、XXXPresenter、创建 Contract 协议类、创建Model,比如一个登录功能就要创建四个文件吗?注册功能又要创建 4 个文件,意味着每个小功能都要创建 4 个文件,带来的问题是文件数量太过于庞大了,所以我想问有什么好的方案优化,你们是怎么处理的?

我的优化:
##### 优化了协议类。不为每个功能创建 XXXContract ,由于我的是组件化工程,每个子工程下公用一个 Contract, 用内部类区分每个功能协议,这样减少了协议类的创建,比如用户模块
代码大致这样子:
```ruby
public class UserContract {

//--------- 微信授权 ----------
public interface WxAuthView extends IView {
}

public interface WxAuthModel extends IModel {
Observable getLoginInfo(Map reqMap);
}

//--------- 绑定手机 ----------
public interface BindPhoneView extends IView {

void enableVerificationCodeBtn(boolean enable);

void setVerificationCodeText(String verificationCodeText);

}

public interface BindPhoneModel extends IModel {

Observable getVerificationCode(Map reqMap);

Observable putBindPhoneNumber(Map reqMap);
}

//--------- 选择区号 ----------
public interface AreaCodeView extends IView {

void showAreaCodeList(List areaCodeBeanList);

void onNetWorkError(String errorMsg);
}

public interface AreaCodeModel extends IModel {
Observable getAreaCodeList(Map reqMap);
}

//--------- 登录 ----------
public interface LoginView extends IView {
void enableVerificationCodeBtn(boolean enable);

void setVerificationCodeText(String verificationCodeText);

void llCodeVisible(boolean visible, int loginType);
}

public interface LoginModel extends IModel {
Observable getVerificationCode(Map reqMap);
Observable getLoginInfo(Map reqMap);
}

//--------- 找回密码 ----------
public interface FindPasswordView extends IView {

void enableVerificationCodeBtn(boolean enable);

void setVerificationCodeText(String verificationCodeText);

}
public interface FindPasswordModel extends IModel {
Observable getVerificationCode(Map reqMap);
Observable putResetPassword(Map reqMap);
}

//--------- 预填资料 ----------
public interface PrepareInfoView extends IView {

}
public interface PrepareInfoModel extends IModel {
Observable postPrepareInfo(Map reqMap);
}

}
```

协议类复用好不好,提出来探讨,你们有什么好的优化方案?

##### 优化了 Model 层,不为每个功能创建 Model ,由于我的组件化工程, 每个子工程复用 Model
代码大致这样子:
```ruby
@ActivityScope
public class UserModel extends BaseModel
implements UserContract.WxAuthModel, UserContract.BindPhoneModel,
UserContract.AreaCodeModel, UserContract.LoginModel,
UserContract.FindPasswordModel, UserContract.PrepareInfoModel {

@Inject
public UserModel(IRepositoryManager mRepositoryManager) {
super(mRepositoryManager);
}

@Override
public Observable getLoginInfo(Map reqMap) {
return mRepositoryManager.obtainRetrofitService(UserService.class)
.getLoginInfo(reqMap);
}

@Override
public Observable getAreaCodeList(Map reqMap) {
return mRepositoryManager.obtainRetrofitService(UserService.class)
.getAreaCodeList(reqMap);
}

@Override
public Observable getVerificationCode(Map reqMap) {
return mRepositoryManager.obtainRetrofitService(UserService.class)
.getVerificationCode(reqMap);
}

@Override
public Observable putResetPassword(Map reqMap) {
return mRepositoryManager.obtainRetrofitService(UserService.class)
.putResetPassword(reqMap);
}

@Override
public Observable putBindPhoneNumber(Map reqMap) {
return mRepositoryManager.obtainRetrofitService(UserService.class)
.putBindPhoneNumber(reqMap);
}

@Override
public Observable postPrepareInfo(Map reqMap) {
return mRepositoryManager.obtainRetrofitService(UserService.class)
.postPrepareInfo(reqMap);
}
}
```
Model复用好不好,提出来探讨,你们有什么好的优化方案?

经过上面优化可以大幅度 Contract 和 Model 的数量,只需要为每个功能创建 XXXActivity 和 XXXPresenter 类,应该每个功能都有自己的逻辑,所以我不建议复用 XXXPresenter。

这样优化的代价是让 DI 层的 XXXModule 层变得臃肿了
代码如下:
```ruby
@Module
public class UserModule {

private UserContract.WxAuthView wxAuthView;
private UserContract.BindPhoneView bindPhoneView;
private UserContract.AreaCodeView areaCodeView;
private UserContract.LoginView loginView;
private UserContract.FindPasswordView findPasswordView;
private UserContract.PrepareInfoView prepareInfoView;

/**
* 构建 ActivityModule 时,将 View 的实现类传入,这样就可以提供 View 的实现类给 Presenter
* @param view
*/
public UserModule(UserContract.WxAuthView view) {
this.wxAuthView = view;
}

public UserModule(UserContract.BindPhoneView view) {
this.bindPhoneView = view;
}

public UserModule(UserContract.AreaCodeView view) {
this.areaCodeView = view;
}

public UserModule(UserContract.LoginView view) {
this.loginView = view;
}

public UserModule(UserContract.FindPasswordView view) {
this.findPasswordView = view;
}

public UserModule(UserContract.PrepareInfoView view) {
this.prepareInfoView = view;
}

//------ 微信授权 ---------
@ActivityScope
@Provides
UserContract.WxAuthView provideWxAuthView() {
return wxAuthView;
}

@ActivityScope
@Provides
UserContract.WxAuthModel provideWxAuthModel(UserModel model) {
return model;
}

//------ 绑定手机号 ---------
@ActivityScope
@Provides
UserContract.BindPhoneView provideBindPhoneView() {
return bindPhoneView;
}

@ActivityScope
@Provides
UserContract.BindPhoneModel provideBindPhoneModel(UserModel model) {
return model;
}

//------ 选择区号 ---------
@ActivityScope
@Provides
UserContract.AreaCodeView provideAreaCodeView() {
return areaCodeView;
}

@ActivityScope
@Provides
UserContract.AreaCodeModel provideAreaCodeModel(UserModel model) {
return model;
}

//------ 登录 ---------
@ActivityScope
@Provides
UserContract.LoginView provideLoginView() {
return loginView;
}

@ActivityScope
@Provides
UserContract.LoginModel provideLoginModel(UserModel model) {
return model;
}

//------ 发现密码 ---------
@ActivityScope
@Provides
UserContract.FindPasswordView provideFindPasswordView() {
return findPasswordView;
}

@ActivityScope
@Provides
UserContract.FindPasswordModel provideFindPasswordModel(UserModel model) {
return model;
}

//------ 提交预填资料 ---------
@ActivityScope
@Provides
UserContract.PrepareInfoView providePrepareInfoView() {
return prepareInfoView;
}

@ActivityScope
@Provides
UserContract.PrepareInfoModel providePrepareInfoModel(UserModel model) {
return model;
}

//------ Other ---------
@ActivityScope
@Provides
Interrupter provideInterrupter() {
Interrupter nsxInterrupter = new Interrupter();
return nsxInterrupter;
}

}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.