本文是对自己使用的项目SimpleMvp的讲解,该项目是在git大神的android10的项目Android-CleanArchitecture基础上进行的更改,有兴趣的可以直接看该大神的源码:(https://github.com/android10/Android-CleanArchitecture)
本文主要讲解如何使用该Mvp框架,对于运用的Dagger2,Rxjava,Retrofit,Lamada技术不做讲解,不了解的哥们可以先自己学习一下。 这里推荐一些学习资料:
Dagger2 使用详解:http://www.jianshu.com/p/94d47da32656
给 Android 开发者的 RxJava 详解:https://gank.io/post/560e15be2dca930e00da1083
RxJava+Retrofit+OkHttp深入浅出:http://blog.csdn.net/wzgiceman/article/details/51939574
作为Presenter和Data层的桥梁,定义Repository接口,由Data层实现。定义UseCase类,从Repository接口获取数据,也就是从其实现类Data层获取数据。
依赖于Domain层,直接从服务器获取需要的数据,并通过实现Domain层的接口,将数据传递到Domain层中。
依赖于Domain层,通过使用Dagger2的依赖注入技术,将Domain层的UseCase注入到Presenter中,同时定义接口,用于向UI层返回数据。
依赖于Presenter层,将Presenter通过依赖注入方式注入到需要请求网络的地方(如:Activity,Adapter,Fragment等等),并实现Presenter层中定义的接口,以便拿到数据
- 分离了视图逻辑和业务逻辑,降低了耦合,可以将业务逻辑写在Domain层中,而视图逻辑可以写到Presenter层中,对于UI层,只用于展示数据
- 简化了UI层的代码,原来一个Activity很容易就上千行代码。使用MVP之后,Activity大大的瘦身了。
- 提供了代码的可读性,方便后期维护
介绍了这么多,现在来看看具体在项目中的应用。在本项目中对代码做了高度封装,就不介绍封装方式了,有兴趣可以自己研究,主要介绍如何使用本项目完成一次网络请求。
其中app对应为UI层,app_common层相当于一个工具类层,将所有层等能用到的放到了这一层,可以忽略不管这个。而app_domain,app_data,app_presenter分别为domain层,data层,presenter层
首先定义IGeneralRepository接口:
public interface IGeneralRepository extends IRepository {
Observable<List<GitUserModel>> getGitUsers();
}
该接口主要目的是衔接Data层和Domain层,Data层有特定类实现类了该接口,从而调用该接口中的方法能返回Data层数据,详细讲解在Data层。
IGeneralRepository接口衔接了Data层,而和Presenter层的交互是通过UseCase进行的:
@Singleton
public class GitUsersUseCase extends UseCaseImpl<IGeneralRepository,Object,List<GitUserModel>> {
/**
* 构造参数
*
* @param repository
* @param workThread 工作线程
* @param resultThread 结果执行线程
*/
@Inject
public GitUsersUseCase(IGeneralRepository repository, ThreadExecutor workThread, PostExecutionThread resultThread) {
super(repository, workThread, resultThread);
}
@Override
protected Observable<List<GitUserModel>> buildUseCaseObservable(Object... objects) {
return getRepository().getGitUsers();
}
}
在该类中通过getRepository().getGitUsers()获取到了IGeneralRepository的实现类中返回的数据,那么只要Presenter层拿到该UseCase对象,就相当于和Domain层建立了连接,而Presenter是依赖Doamin层,所以拿到对象很容易,不过我们这里使用的是Dagger2依赖注入拿到的UseCase对象,关于Dagger2的使用这里不做介绍。以后有时间单讲。
Domain层不仅连接了Data层和Presenter层,同时,它也起到了一个约束的作用,所有请求和Data有关的代码都是这样做,这时,即使不写代码注释,思路依然很清闲,扩展性很强。
由于data层的数据来源很多,服务器、本地Json、数据库、内存等,这里我单独总结了一下,见个人博客:http://laomao.space/2017/03/15/SimpleMvp-Data/
通过dagger2得到Domain层中的UseCase对象。
@Module
public class GeneralModule {
@Provides
@Named(Constants.NAMED_GIT_USERS)
UseCase<Object,List<GitUserModel>> provideGitUsersUseCase(IGeneralRepository repository, ThreadExecutor executor, PostExecutionThread thread){
return new GitUsersUseCase(repository,executor,thread);
}
}
接着定义一个接口IGitUsersView用于连接UI层和Presenter层
public interface IGitUsersView extends ILoadingView{
void onGetGitUsers(List<GitUser> users);
}
这个时候只需要一个中间者,将从UseCase中获取到的数据,传递给接口中的onGetGitUsers(List users),那么实现了该接口的UI层就能拿到了数据,这个中间者就是Presenter
public class GitUsersPresenter extends LoadingPresenter<Object,Object,List<GitUserModel>,List<GitUser>,IGitUsersView> {
private GitUserMapper mGMapper;
@Inject
public GitUsersPresenter(
@Named(Constants.NAMED_GIT_USERS)
@NonNull UseCase<Object, List<GitUserModel>> useCase, GitUserMapper gMapper) {
super(useCase);
mGMapper = gMapper;
}
@Override
public void initialize(Object... objects) {
execute(objects);
}
@Override
public void onNext(List<GitUserModel> gitUserModels) {
super.onNext(gitUserModels);
getView().onGetGitUsers(mGMapper.transform(gitUserModels));
}
}
可以看到在onNext方法中,返回了数据,具体怎么返回在GitUsersPresenter的父类中封装的呢,有兴趣自己研究,通过getView拿到IGitUsersView接口对象,并把数据传递给onGetGitUsers()方法。
首先使用@Component注解一个连接器GeneralComponent
@PerActivity
@Component(dependencies = ApplicationComponent.class,modules = {ActivityModule.class, GeneralModule.class})
public interface GeneralComponent extends ActivityComponent{
void inject(GitUsersActivity activity);
}
它的作用是让那些想要使用Dagger2依赖注入的地方提供一个通道,而那些要使用地方来这里登记一下void inject(GitUsersActivity activity);因为我们在GitUsersActivity中要使用Presenter,所以这里将这个Activity登记一下。
public class GitUsersActivity extends BaseActivity implements IGitUsersView {
@Inject
GitUsersPresenter mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_git_users);
// 初始化网络请求
DaggerGeneralComponent.builder().applicationComponent(getApplicationComponent()).activityModule(getActivityModule()).build().inject(this);
mPresenter.setView(this);
// 发起网络请求
mPresenter.initialize();
}
/**
* 网络请求返回数据
* @param users
*/
@Override
public void onGetGitUsers(List<GitUser> users) {
// 处理网络返回数据
}
}
这里把GitUsersPresenter注入到了GitUsersActivity中,虽然注入了,但GitUsersActivity不知道去哪里找,所以需要将GitUsersActivity在GeneralComponent中登记一下,DaggerGeneralComponent.builder().applicationComponent(getApplicationComponent()).activityModule(getActivityModule()).build().inject(this); 这个时候就可以使用Presenter实例了,使用mPresenter.setView(this)给Presenter设置View对象,这里用this是因为activity实现了Presenter层的接口IGitUserView,这样Presenter层就能拿到接口的实例对象,从而给UI层返回数据。最后通过mPresenter.initialize()发起网络请求,当然如果有参数可以在initialize()方法中添加。最后数据就通过实现了IGitUserView接口的onGetGitUsers(List users)方法返回。
至此,就成功的完成了一次网络请求。刚开始学习使用MVP,是很痛苦的,莫名其妙的加大了好多工作量,但是,如果你能坚持下来,你会发现后期维护起来非常容易。
自从使用了MVP,妈妈再也不用担心我打产品经理了。
哈哈哈哈哈。。。。。。
文笔太差,有不足地方请指正