前段時間在天星羣中有朋友說到了clean架構。恰好在最近的項目裏面我在搭建框架的時候用到了clean,因此在這裏就把搭建過程在這裏描述一下。Demo在文章末尾。本文側重於clean的搭建,mvp+rxjava的部分,不作介紹。
(咦?我聽到有人在問什麼是天星羣。既然你誠心誠意的發問了,那我就給大家透露一下。天星是一羣Android開發者閒的沒事幹搞的一個博客團隊,這是團隊博客地址:點這裏,這個是粉絲qq羣:557247785。歡迎妹子和女裝大佬們!)html
mvp和rxjava基本是如今開發標配,有不少寫的比較好的文章。對mvp和rxjava比較熟的同窗能夠繼續往下看了。還不熟的同窗能夠看看MVP,Rxjava1,Rxjava2。java
Clean是一種架構的思想,跟MVP同樣,解耦就完事兒了。(那一羣解耦狂魔,你根本不知道他們究竟想怎樣!)關於clean框架的解析不少,我再也不贅述,畢竟本文是手把手寫一個Demo。react
Clean思想由Uncle Bob提出的,英文不錯的看這個 The Clean Code Blog
Google爸爸寫的Demo能夠做爲參考todo‑mvp‑clean
android10的文章圖解多,比較容易理解,推薦!Android-CleanArchitecture
中文版能夠看看來自谷歌清潔工的Clean架構探討,我以爲講的很好。android
按慣例這裏該有一張表情包,可是我沒有找到能夠皮的理由,因此,算了。git
如今來模擬一個登錄功能。mvp是clean架構的基礎,咱們先把mvp+rxjava的框架給弄好。個人項目結構是這樣的。 github
分爲了data,domain,presentation 三層。分別對應clean的三層。 data層和presentation層你們應該都比較熟悉,就是一些mvp的東西。 那這個domain layout是幹嗎的?bash
業務邏輯,use case實現的地方 之前在mvp架構的時候,咱們會說。我要是不知道這個app能幹嗎,看一眼presenter的接口就知道了。那在clean裏面就能夠說。我要是不知道這app能幹嗎,看一眼domain層就知道了。
usecase更加簡化了presenter裏面的代碼 之前presenter裏面會調用data層的東西,如今presenter只管負責的usecase。代碼量大大的減小。
usecase純java代碼,不含androd依賴架構
那usecase是幹嗎的? 看看google官方todo‑mvp‑clean裏面Usecase在幹嗎,又是如何調用的。app
使用哪一個方法的時候,就調用傳入哪一個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/…