Android 干净的体系结构、用例和实体
好的,我刚刚开始了一个新的Android项目,想尝试实现Bob叔叔的Clean架构。我在使用RxJava和GitHub示例和样板以及Fernando Cerjas的博客(比如)中的东西方面有了一个很好的开端,但是对于如何实现一些用例,我仍然有一些问题Android 干净的体系结构、用例和实体,android,architecture,clean-architecture,Android,Architecture,Clean Architecture,好的,我刚刚开始了一个新的Android项目,想尝试实现Bob叔叔的Clean架构。我在使用RxJava和GitHub示例和样板以及Fernando Cerjas的博客(比如)中的东西方面有了一个很好的开端,但是对于如何实现一些用例,我仍然有一些问题 TL;博士 一个实体的字段是否应该是另一个实体(在我的示例中,User具有列表字段) 或者演示者应该结合用例来构建映射到多个实体上的ViewModel(那么如何对映射器进行编码?) 或者演示者是否应该将ViewModel与每个用例/实体关联,并创
TL;博士 一个实体的字段是否应该是另一个实体(在我的示例中,
User
具有列表
字段)
或者演示者应该结合用例来构建映射到多个实体上的ViewModel(那么如何对映射器进行编码?)
或者演示者是否应该将ViewModel与每个用例/实体关联,并创建某种“等待所有数据到onNext”来为每个ViewModel调用view.show()
基本上,用例应该只返回实体吗?一个实体是否可以由其他实体组成(如在类的字段中)?实体只是哑数据模型POJO吗?如何表示“joinsql”查询
作为一个例子,让我们使用一个简单的用户/消息应用程序。 我想实现两个视图:
UserList
和UserDetails
:
显示UserList
用户列表
显示用户信息及其最新消息UserDetails
UserList
非常简单,我可以看到如何编写相关的用例和层(下面的代码)
我的问题是UserDetails
屏幕
如果我希望所有数据同时在视图中传递(如构建由用户类和字段列表组成的ViewModel),我应该如何编写我的GetUserInfoUseCase
?GetUserInfoUseCase
的返回值应该是多少?
我是否应该编写一个可观察的GetUserInfoUseCase
和一个可观察的GetUserLatestMessages
并在演示者中以某种方式合并它们?如果是的话,我如何管理这一点,因为我的演示者中没有观察者(我只传递一个观察者作为我的用例参数)
用户实体
消息实体
GetUsersUseCase
public类GetUsersUseCase扩展了UseCaseObservableWithParameter{
@注入
公共GetUsersSecase(UsersRepository UsersRepository,
@命名(“线程”)调度程序threadScheduler,
@命名(“PostExecution”)计划程序(postExecutionScheduler){
超级(usersRepository、threadScheduler、postExecutionScheduler);
}
@凌驾
受保护的可观察buildObservable(布尔forceRefresh){
如果(强制刷新)
repository.invalidateCache();
返回repository.getUsers();
}
}
UsersPresenter
公共类UsersPresenter扩展BasePresenter实现UsersContract.Presenter{
@注入
GetUsersUseCase-mGetUsersUseCase;
@注入
UserViewModelMapper mUserMapper;
@注入
公共用户spresenter(){
}
@凌驾
public void attachView(UsersContract.View mvpView){
super.attachView(mvpView);
}
@凌驾
公共视图(){
super.detachView();
mGetUsersUseCase.unsubscribe();
}
@凌驾
公共用户(布尔强制刷新){
getMvpView().showProgress();
执行(forceRefresh,new DisposableObserver()){
@凌驾
public void onNext(列出用户){
getMvpView().hideProgress();
getMvpView().showUsers(mUsersMapper.mapUsersToViewModels(users));
}
@凌驾
未完成的公共空间(){
}
@凌驾
公共无效申报人(可丢弃的e){
getMvpView().hideProgress();
getMvpView().batherRorMessage(如getMessage());
}
});
}
}
UseCaseObservableWithParameter
公共抽象类UseCaseObservableWithParameter扩展了UseCase{
public UseCaseObservableWithParameter(存储库存储库、调度程序线程调度程序、调度程序执行后调度程序){
超级(存储库、threadScheduler、postExecutionScheduler);
}
受保护的抽象可观察buildObservable(请求数据请求数据);
public void execute(请求\数据请求数据,可处置观察者useCaseSubscriber){
这个是一次性的(
此.buildObservable(requestData)
.subscribeOn(线程调度程序)
.observeOn(执行后调度程序)
.subscribeWith(useCaseSubscriber)
);
}
}
用例
公共抽象类用例{
受保护的最终存储库;
受保护的最终调度程序线程调度程序;
受保护的最终调度程序postExecutionScheduler;
受保护的CompositeDisposable一次性=新CompositeDisposable();
公共用例(存储库,
@命名(“线程”)调度程序threadScheduler,
@命名(“PostExecution”)计划程序(postExecutionScheduler){
Timber.d(“用例系数”);
this.repository=存储库;
this.threadScheduler=threadScheduler;
this.postExecutionScheduler=postExecutionScheduler;
}
受保护的抽象可观察buildObservable(请求数据请求数据);
公共布尔值isUnsubscribed(){
返回一次性.size()==0;
}
公开作废取消订阅(){
如果(!isUnsubscribed()){
一次性的;
}
}
}
一个问题中有很多问题。让我试着巩固我认为我理解的是你的关键问题
- 实体可以相互引用吗?答案是:是的。也在 Clean Architecture u可以创建实体互连的域模型
- 用例应该返回什么?
答:用例定义输入DTO(数据传输对象)和输出DTO,这对用例来说是最方便的。在他的书中,鲍勃叔叔
public abstract class User { public abstract long id(); public abstract String name(); ... }
public abstract class Message { public abstract long id(); public abstract long senderId(); public abstract String text(); public abstract long timstamp(); ... }
public class GetUsersUseCase extends UseCaseObservableWithParameter<Boolean, List<User>, UsersRepository> { @Inject public GetUsersUseCase(UsersRepository UsersRepository, @Named("Thread") Scheduler threadScheduler, @Named("PostExecution") Scheduler postExecutionScheduler) { super(usersRepository, threadScheduler, postExecutionScheduler); } @Override protected Observable<List<User>> buildObservable(Boolean forceRefresh) { if(forceRefresh) repository.invalidateCache(); return repository.getUsers(); } }
public class UsersPresenter extends BasePresenter<UsersContract.View> implements UsersContract.Presenter { @Inject GetUsersUseCase mGetUsersUseCase; @Inject UserViewModelMapper mUserMapper; @Inject public UsersPresenter() { } @Override public void attachView(UsersContract.View mvpView) { super.attachView(mvpView); } @Override public void detachView() { super.detachView(); mGetUsersUseCase.unsubscribe(); } @Override public void fetchUsers(boolean forceRefresh) { getMvpView().showProgress(); mGetUsersUseCase.execute(forceRefresh, new DisposableObserver<List<User>>() { @Override public void onNext(List<User> users) { getMvpView().hideProgress(); getMvpView().showUsers(mUsersMapper.mapUsersToViewModels(users)); } @Override public void onComplete() { } @Override public void onError(Throwable e) { getMvpView().hideProgress(); getMvpView().showErrorMessage(e.getMessage()); } }); } }
public abstract class UseCaseObservableWithParameter<REQUEST_DATA, RESPONSE_DATA, REPOSITORY> extends UseCase<Observable, REQUEST_DATA, RESPONSE_DATA, REPOSITORY> { public UseCaseObservableWithParameter(REPOSITORY repository, Scheduler threadScheduler, Scheduler postExecutionScheduler) { super(repository, threadScheduler, postExecutionScheduler); } protected abstract Observable<RESPONSE_DATA> buildObservable(REQUEST_DATA requestData); public void execute(REQUEST_DATA requestData, DisposableObserver<RESPONSE_DATA> useCaseSubscriber) { this.disposable.add( this.buildObservable(requestData) .subscribeOn(threadScheduler) .observeOn(postExecutionScheduler) .subscribeWith(useCaseSubscriber) ); } }
public abstract class UseCase<OBSERVABLE, REQUEST_DATA, RESPONSE_DATA, REPOSITORY> { protected final REPOSITORY repository; protected final Scheduler threadScheduler; protected final Scheduler postExecutionScheduler; protected CompositeDisposable disposable = new CompositeDisposable(); public UseCase(REPOSITORY repository, @Named("Thread") Scheduler threadScheduler, @Named("PostExecution") Scheduler postExecutionScheduler) { Timber.d("UseCase CTOR"); this.repository = repository; this.threadScheduler = threadScheduler; this.postExecutionScheduler = postExecutionScheduler; } protected abstract OBSERVABLE buildObservable(REQUEST_DATA requestData); public boolean isUnsubscribed() { return disposable.size() == 0; } public void unsubscribe() { if (!isUnsubscribed()) { disposable.clear(); } } }