/SimpleMvp

MVP+Dagger+Rxjava+Retrofit+Lamada

Primary LanguageJava

SimpleMvp

本文是对自己使用的项目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

mvp介绍

Domain层

作为Presenter和Data层的桥梁,定义Repository接口,由Data层实现。定义UseCase类,从Repository接口获取数据,也就是从其实现类Data层获取数据。

Data层

依赖于Domain层,直接从服务器获取需要的数据,并通过实现Domain层的接口,将数据传递到Domain层中。

Presenter层

依赖于Domain层,通过使用Dagger2的依赖注入技术,将Domain层的UseCase注入到Presenter中,同时定义接口,用于向UI层返回数据。

UI层

依赖于Presenter层,将Presenter通过依赖注入方式注入到需要请求网络的地方(如:Activity,Adapter,Fragment等等),并实现Presenter层中定义的接口,以便拿到数据

image

mvp模式好处

  • 分离了视图逻辑和业务逻辑,降低了耦合,可以将业务逻辑写在Domain层中,而视图逻辑可以写到Presenter层中,对于UI层,只用于展示数据
  • 简化了UI层的代码,原来一个Activity很容易就上千行代码。使用MVP之后,Activity大大的瘦身了。
  • 提供了代码的可读性,方便后期维护

撸代码

介绍了这么多,现在来看看具体在项目中的应用。在本项目中对代码做了高度封装,就不介绍封装方式了,有兴趣可以自己研究,主要介绍如何使用本项目完成一次网络请求。

项目结构

image

其中app对应为UI层,app_common层相当于一个工具类层,将所有层等能用到的放到了这一层,可以忽略不管这个。而app_domain,app_data,app_presenter分别为domain层,data层,presenter层

domain层代码

image

首先定义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层代码

由于data层的数据来源很多,服务器、本地Json、数据库、内存等,这里我单独总结了一下,见个人博客:http://laomao.space/2017/03/15/SimpleMvp-Data/

presenter层代码

image

通过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()方法。

UI层代码

image

首先使用@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,妈妈再也不用担心我打产品经理了。

哈哈哈哈哈。。。。。。

文笔太差,有不足地方请指正