Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/185.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 干净的体系结构、用例和实体_Android_Architecture_Clean Architecture - Fatal编程技术网

Android 干净的体系结构、用例和实体

Android 干净的体系结构、用例和实体,android,architecture,clean-architecture,Android,Architecture,Clean Architecture,好的,我刚刚开始了一个新的Android项目,想尝试实现Bob叔叔的Clean架构。我在使用RxJava和GitHub示例和样板以及Fernando Cerjas的博客(比如)中的东西方面有了一个很好的开端,但是对于如何实现一些用例,我仍然有一些问题 TL;博士 一个实体的字段是否应该是另一个实体(在我的示例中,User具有列表字段) 或者演示者应该结合用例来构建映射到多个实体上的ViewModel(那么如何对映射器进行编码?) 或者演示者是否应该将ViewModel与每个用例/实体关联,并创

好的,我刚刚开始了一个新的Android项目,想尝试实现Bob叔叔的Clean架构。我在使用RxJava和GitHub示例和样板以及Fernando Cerjas的博客(比如)中的东西方面有了一个很好的开端,但是对于如何实现一些用例,我仍然有一些问题


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();
            }
        }
    }