前段时间在天星群中有朋友说到了clean架构。刚好在最近的项目里面我在搭建框架的时候用到了clean,所以在这里就把搭建过程在这里描述一下。Demo在文章末尾。本文侧重于clean的搭建,mvp+rxjava的部分,不做介绍。
(咦?我听到有人在问什么是天星群。既然你诚心诚意的发问了,那我就给你们透露一下。天星是一群Android开发者闲的没事干搞的一个博客团队,这是团队博客地址:点这里,这个是粉丝qq群:557247785。欢迎妹子和女装大佬们!)
mvp和rxjava基本是现在开发标配,有很多写的比较好的文章。对mvp和rxjava比较熟的同学可以继续往下看了。还不熟的同学可以看看MVP, Rxjava1 , Rxjava2 。
Clean是一种架构的思想,跟MVP一样,解耦就完事儿了。(那一群解耦狂魔,你根本不知道他们究竟想怎样!)关于clean框架的解析很多,我不再赘述,毕竟本文是手把手写一个Demo。
Clean思想由Uncle Bob提出的,英文不错的看这个The Clean Code Blog
Google爸爸写的Demo可以作为参考 todo‑mvp‑clean
android10的文章图解多,比较容易理解,推荐! Android-CleanArchitecture
中文版可以看看来自谷歌清洁工的Clean架构探讨,我觉得讲的很好。
按惯例这里该有一张表情包,但是我没有找到可以皮的理由,所以,算了。
现在来模拟一个登陆功能。mvp是clean架构的基础,我们先把mvp+rxjava的框架给弄好。我的项目结构是这样的。
分为了data,domain,presentation 三层。分别对应clean的三层。 data层和presentation层大家应该都比较熟悉,就是一些mvp的东西。 那这个domain layout是干嘛的?
业务逻辑,use case实现的地方以前在mvp架构的时候,我们会说。我要是不知道这个app能干嘛,看一眼presenter的接口就知道了。那在clean里面就可以说。我要是不知道这app能干嘛,看一眼domain层就知道了。
usecase更加简化了presenter里面的代码以前presenter里面会调用data层的东西,现在presenter只管负责的usecase。代码量大大的减少。
usecase纯java代码,不含androd依赖
那usecase是干嘛的? 看看google官方 todo‑mvp‑clean 里面Usecase在干嘛,又是如何调用的。
使用哪个方法的时候,就调用传入哪个usecase,和请求需要的参数,和相应的回调接口。
UseCaseHandler主要作用就是统一管理,回调直观。 当我们把rxjava2加入进来之后,UseCaseHandler就没有存在的意义了。 去掉handler,不需要绑定这杂七杂八的东西之后,usecase可以简化了。所以我的BaseUseCase是这样的
public abstract class BaseUseCase<P, Q> { private final Scheduler observerThread; private final Scheduler subcriberThread; private final CompositeDisposable disposables; public BaseUseCase(Scheduler observerThread, Scheduler subcriberThread) { this.observerThread = observerThread; this.subcriberThread = subcriberThread; this.disposables = new CompositeDisposable(); } protected abstract Observable<Q> buildUseCaseObservable(P request); public void execute(DisposableObserver<Q> observer, P request) { Preconditions.checkNotNull(observer); final Observable<Q> observable = this.buildUseCaseObservable(request) .subscribeOn(observerThread) .observeOn(subcriberThread); addDisposable(observable.subscribeWith(observer)); } public void dispose() { if (!disposables.isDisposed()) { disposables.dispose(); } } public void addDisposable(Disposable disposable) { Preconditions.checkNotNull(disposable); Preconditions.checkNotNull(disposables); disposables.add(disposable); } } 复制代码
跟google的demo做了一样的事,不过加了CompositeDisposable统一管理而已。
public class LoginUseCase extends BaseUseCase<LoginUseCase.RequestValue, User> { private final Repository repository; public LoginUseCase(Scheduler observerThread, Scheduler subcriberThread, Repository repository) { super(observerThread, subcriberThread); this.repository = repository; } @Override protected Observable<User> buildUseCaseObservable(RequestValue request) { return repository.getUser(request.account, request.password); } public static final class RequestValue { final String account; final String password; public RequestValue(String account, String password) { this.account = Preconditions.checkNotNull(account); this.password = Preconditions.checkNotNull(password); } } } 复制代码
跟google的demo差不多基本一致,把ResponseValue改成了返回的实体类。
@Override public void login(String account, String password) { loginUseCase.execute(new LoginObserver(), new LoginUseCase.RequestValue(account, password)); } private final class LoginObserver extends DisposableObserver<User> { @Override public void onNext(User user) { loginUseCase.saveUser(user); } @Override public void onError(Throwable e) { } @Override public void onComplete() { } } 复制代码
/*ButterKnife*/ implementation 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' /*GreenDao*/ implementation 'org.greenrobot:greendao:3.2.2' /*Retrofit*/ implementation 'com.squareup.retrofit2:retrofit:2.0.2' implementation 'com.squareup.okhttp3:okhttp:3.1.2' implementation 'com.squareup.retrofit2:converter-gson:2.3.0' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.5.0' /*Rxjava2*/ implementation 'io.reactivex.rxjava2:rxjava:2.1.3' implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' 复制代码
全部源码在这里: github.com/GuitarDian/…