Android 清洁架构开源项目指南:打造可维护的应用
Android 清洁架构开源项目指南:打造可维护的应用
许多开发者在开发过程中会遇到这样的问题:随着应用功能的增加,代码变得混乱且难以维护,新功能的开发也变得困难重重。本文将介绍如何利用Android清洁架构来解决这些问题。
清洁架构简介
清洁架构(Clean Architecture)是由Robert C. Martin提出的架构模式,旨在通过分层设计实现代码的解耦,提高代码的可维护性和可测试性。
架构分层
各层职责
| 层级 | 职责 | 关键技术组件 |
|---|---|---|
| 表现层(Presentation Layer) | 用户界面展示与交互处理 | Activity, Fragment, Presenter, ViewModel |
| 领域层(Domain Layer) | 核心业务逻辑 | UseCase, Interactor, Entity, Repository接口 |
| 数据层(Data Layer) | 数据获取与持久化 | Repository实现, DataSource, API, Database |
项目结构分析
领域层:业务核心
public class UserProfile {
private final int profileId;
private String name;
private String email;
private String bio;
public UserProfile(int profileId) {
this.profileId = profileId;
}
public int getId() { return profileId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// 更多getter/setter...
}
用例层:业务逻辑封装
public abstract class BusinessOperation {
private final Executor backgroundExecutor;
private final MainThread mainThread;
private final CompositeDisposable disposables;
protected abstract Observable<T> createObservable(Params params);
public void execute(Observer<T> observer, Params params) {
Preconditions.checkNotNull(observer);
final Observable<T> observable = createObservable(params)
.subscribeOn(Schedulers.from(backgroundExecutor))
.observeOn(mainThread.getScheduler());
addDisposable(observable.subscribeWith(observer));
}
public void dispose() {
if (!disposables.isDisposed()) {
disposables.dispose();
}
}
}
数据层:数据管理
public class ProfileDataRepo implements ProfileRepository {
private final ProfileDataSourceFactory dataSourceFactory;
private final ProfileEntityMapper entityMapper;
@Override
public Observable fetchProfiles() {
final ProfileDataSource dataSource = dataSourceFactory.createCloudDataSource();
return dataSource.fetchProfileEntities()
.map(entities -> entityMapper.mapToProfiles(entities));
}
}
表现层:界面展示
public class ProfileListPresenter implements Presenter {
private ProfileListView profileView;
private final FetchProfiles fetchProfilesUseCase;
private final ProfileDataMapper dataMapper;
public void start() {
loadProfiles();
}
private void loadProfiles() {
hideRetryView();
showLoading();
fetchProfiles();
}
private void fetchProfiles() {
fetchProfilesUseCase.execute(new ProfilesObserver(), null);
}
private final class ProfilesObserver extends DefaultObserver {
@Override public void onNext(List<UserProfile> profiles) {
ProfileListPresenter.this.displayProfiles(profiles);
}
@Override public void onError(Throwable e) {
ProfileListPresenter.this.showError(new ErrorBundle((Exception) e));
ProfileListPresenter.this.showRetry();
}
}
}
依赖注入
本项目采用Dagger 2实现依赖注入:
@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {
void inject(MyApplication app);
Context appContext();
Executor threadExecutor();
MainThread mainThread();
ProfileRepository profileRepository();
}
@PerActivity
@Component(dependencies = AppComponent.class, modules = ActivityModule.class)
public interface ActivityComp {
void inject(ProfileListActivity activity);
void inject(ProfileDetailActivity activity);
}
测试方法
领域层测试
public class FetchProfilesTest {
private FetchProfiles fetchProfiles;
private MockProfileRepository mockRepo;
private MockMainThread mockMainThread;
private MockExecutor mockExecutor;
@Test
public void testFetchProfilesObservable() {
fetchProfiles.createObservable(null).test().assertValue(PROFILE_LIST);
}
}
表现层测试
public class ProfileListPresenterTest {
@Mock private ProfileListView mockView;
@Mock private FetchProfiles mockFetchProfiles;
@Mock private ProfileDataMapper mockMapper;
private ProfileListPresenter presenter;
@Test
public void testPresenterStart() {
presenter.start();
verify(mockView).showLoading();
verify(mockFetchProfiles).execute(any(DefaultObserver.class), eq(null));
}
}
开发指南
环境设置
# 克隆仓库
git clone https://gitcode.com/gh_mirrors/an/Android-CleanArchitecture
# 构建项目
./gradlew assembleDebug
# 运行单元测试
./gradlew test
# 运行验收测试
./gradlew connectedCheck
添加新功能
- 领域层:定义实体和用例
- 数据层:实现仓库和数据源
- 表现层:创建表示器和视图
- 配置依赖注入:更新Dagger模块
编码建议
- 采用清晰的包结构
- 遵循单一职责原则
- 编写充分的单元测试
- 使用一致的命名约定
总结
Android清洁架构为大型应用提供了良好的架构方案,能够显著提升代码的可维护性和可测试性。尽管初期学习成本较高,但从长远来看,这是一项值得的投资。