在这里插入图片描述

从 2010 年至今,Android 架构的迭代始终围绕“解耦、可维护、可测试”的核心目标,一步步从“代码堆砌”走向“规范化设计”。本文将通过 7 个阶段梳理这段进化史。

TLDR:

时间范围 核心技术/架构 核心特点 适用场景
2010-2013 无架构,裸写 Activity/Fragment 开发快、新手易上手;代码臃肿耦合、不可测试、维护难 超小型 Demo、一次性功能验证
2013-2016 MVP + 手动依赖管理 关注点分离、Activity 瘦身、Presenter 可测;易内存泄漏、回调嵌套 中小型 App、基础分层需求
2014-2017 Clean Architecture + Dagger 业务与框架解耦、复用性强;分层复杂、开发成本高 中大型 App、长期可维护性项目
2016-2019 MVVM + AAC + Repository 生命周期感知、响应式绑定、数据统一;DataBinding 可读性争议 绝大多数中小型 App
2017-2020 MVVM + RxJava + 单向数据流萌芽 异步逻辑简洁、数据流可控;学习成本高、代码易晦涩 中大型 App、复杂异步场景
2019-2022 MVVM + Coroutines + Flow 异步代码简洁、背压友好、状态可控;需掌握 Kotlin 协程 主流中小到中大型 App
2020-2025 MVI + Jetpack Compose + 状态机 状态可预测、声明式 UI 高效、测试友好;学习门槛高 大型复杂 App、极致可维护性需求

Phase 1:前架构时代(2010-2013)

这是 Android 开发的“蛮荒期”——没有任何架构概念,所有逻辑都塞进 Activity/Fragment:网络请求用 AsyncTask 写在页面里,数据解析和 UI 更新混在一起,甚至业务判断也直接嵌套在点击事件中。

当时设备性能有限,“能跑起来”就是唯一标准,没人在意代码结构。结果是 Activity 动辄上千行,成了“万能类”:生命周期 Bug 频发,改一行代码要翻半小时,团队协作时合并冲突比“拼拼图”还乱,而且几乎无法做单元测试,只能靠手动点击验证功能。这段经历让开发者明白:不做关注点分离,早晚会被复杂度淹没

Phase 2:MVP 时代(2013-2016)

在这里插入图片描述

为了拯救臃肿的 Activity,MVP(Model-View-Presenter)成了首个普及的架构模式:View 层由 Activity/Fragment 承担,只负责 UI 渲染和转发用户事件;Presenter 作为中间层,接收 View 的请求,调用 Model 处理业务逻辑,再通知 View 更新;Model 则封装数据操作(网络、数据库)。

这种分层让 Activity 终于“瘦身”,Presenter 也能独立写单元测试,但缺点也很明显:页面复杂时 Presenter 会变得臃肿,回调嵌套成“金字塔”,而且 Presenter 持有 View 引用,生命周期管理不当就会内存泄漏。不过,这是 Android 圈第一次大规模实践“关注点分离”,为后续架构打下了基础。

interface LoginView {
    fun showLoading()
    fun showError(msg: String)
    fun showSuccess(user: User)
}

class LoginPresenter(
    private val authRepo: AuthRepository,
    private val view: LoginView
) {
    fun onLoginClick(email: String, pass: String) {
        view.showLoading()
        authRepo.login(email, pass,
            onSuccess = { view.showSuccess(it) },
            onError = { view.showError(it.message ?: "Unknown error") }
        )
    }
}

Phase 3:Clean Architecture 与依赖注入(2014-2017)

在这里插入图片描述

MVP 解决了“页面臃肿”,但业务逻辑的耦合依然严重,于是 Clean Architecture(分层架构)和依赖注入(Dagger)来了。Clean Architecture 把代码分成多层:外层是 UI 和框架相关的代码,内层是独立于框架的核心业务逻辑(用例、实体),依赖只能从外层指向内层,确保核心逻辑不被框架绑定。

同时,Dagger 开始普及,替代了手动创建对象的繁琐,让 Presenter、Model 的依赖关系更清晰。这一阶段,开发者终于能做到“业务逻辑独立于 Android 框架”,代码的可复用性和可测试性大幅提升,但也带来了新的复杂度:分层太多导致开发成本变高,小型项目用起来反而“小题大做”。

Clean Architecture 首次引入 Domain 层,并通过用例(UseCase)实现相关逻辑。

// Domain layer (pure Kotlin)
data class User(val id: String, val email: String)

interface AuthRepository {
    fun login(email: String, password: String): Single<User>
}
class LoginUseCase(private val repo: AuthRepository) {
    fun execute(email: String, pass: String) = repo.login(email, pass)
}

同时,“仓库模式(Repository)”开始普及,统一封装网络和本地数据的访问逻辑,让 Domain 层不用关心数据来源。

//  Data Layer — Implementation Details Live Here
class AuthRepositoryImpl(private val api: AuthApi) : AuthRepository {
    override fun login(email: String, pass: String) =
        api.login(LoginRequest(email, pass)).map { dto -> dto.toDomain() }
}

interface AuthApi {
    @POST("auth/login")
    fun login(@Body body: LoginRequest): Single<UserDto>
}

DI 用来为各 Layer 快速注入必要组件,建立通信

// DI: Dagger 2 connected the layers automatically
@Module
abstract class RepositoryModule {
    @Binds abstract fun bindAuthRepository(impl: AuthRepositoryImpl): AuthRepository
}

Phase 4:MVVM 与架构组件(2016-2019)

在这里插入图片描述

Google 推出 Android Architecture Components(ViewModel、LiveData、Room),直接推动 MVVM(Model-View-ViewModel)成为主流。

ViewModel 负责管理页面数据,生命周期与 Activity 解耦,不怕屏幕旋转丢失数据;LiveData 作为响应式容器,数据变化时自动通知 UI,不用再写一堆回调;Room 则简化了数据库操作,避免了原生 SQL 的繁琐。

class LoginViewModel(
    private val authRepo: AuthRepository
) : ViewModel() {

private val _state = MutableLiveData<LoginState>(LoginState.Idle)
    val state: LiveData<LoginState> = _state
    fun login(email: String, pass: String) = viewModelScope.launch {
        _state.value = LoginState.Loading
        runCatching { authRepo.login(email, pass) }
            .onSuccess { _state.value = LoginState.Success(it) }
            .onFailure { _state.value = LoginState.Error(it.message ?: "Oops") }
    }
}
sealed class LoginState {
    data object Idle : LoginState()
    data object Loading : LoginState()
    data class Success(val user: User) : LoginState()
    data class Error(val msg: String) : LoginState()
}

MVVM 让代码更简洁:Activity 只负责观察数据,ViewModel 只处理业务,数据和 UI 的绑定更自然,但早期的 DataBinding 也带来了一些争议——XML 中写过多逻辑会降低可读性。

viewModel.state.observe(this) { state ->
    when (state) {
        is LoginState.Loading -> showProgress()
        is LoginState.Success -> showWelcome(state.user)
        is LoginState.Error   -> showError(state.msg)
        else -> Unit
    }
}

Phase 5:RxJava 与单向数据流萌芽(2017-2020)

在这里插入图片描述

随着 App 功能越来越复杂,异步操作和数据流管理成了新痛点,RxJava 的出现让“响应式编程”成了主流:用 Observable 封装数据流,通过操作符(map、flatMap)处理异步逻辑,替代了回调嵌套。

同时,单向数据流(UDF)的概念开始萌芽——数据只能从数据源→ViewModel→UI 单向流动,用户操作通过事件通知 ViewModel 更新数据,再由数据驱动 UI 刷新,避免了状态混乱。不过,RxJava 的学习成本较高,操作符滥用会让代码变得晦涩,这也为后续 Coroutines 的崛起埋下了伏笔。

Phase 6:Coroutines+Flow 与 MVVM 普及(2019-2022)

在这里插入图片描述

Kotlin 的 Coroutines 和 Flow 解决了 RxJava 的痛点:用更简洁的“协程”替代了复杂的 Observable,用“Flow”实现响应式数据流,代码可读性大幅提升。

这一阶段,MVVM 彻底成为默认架构:ViewModel 用 Coroutines 处理异步任务,用 Flow 封装数据流,LiveData 逐渐被 StateFlow 替代(支持背压、更适合 Kotlin)。

class LoginViewModel(
    private val authRepo: AuthRepository
) : ViewModel() {

var uiState by mutableStateOf<LoginUiState>(LoginUiState.Idle)
        private set
    fun login(email: String, pass: String) = viewModelScope.launch {
        uiState = LoginUiState.Loading
        try {
            val user = authRepo.login(email, pass) // suspend function
            uiState = LoginUiState.Success(user)
        } catch (e: Exception) {
            uiState = LoginUiState.Error(e.message ?: "Network error")
        }
    }
}
sealed class LoginUiState {
    data object Idle : LoginUiState()
    data object Loading : LoginUiState()
    data class Success(val user: User) : LoginUiState()
    data class Error(val msg: String) : LoginUiState()
}

同时,“单向数据流”的实践更成熟,页面状态(加载中/成功/失败)被封装成密封类,状态切换更可控。MVVM+Coroutines+Flow 的组合,平衡了“简洁性”和“可维护性”,成了中小项目的首选架构。

class UserRepository(
    private val api: UserApi
) {
    fun observeUser(id: String): Flow<User> = flow {
        while (true) {
            emit(api.getUser(id))       // emit latest user data
            delay(10_000)               // refresh every 10 s
        }
    }.flowOn(Dispatchers.IO)
}
viewModelScope.launch {
    userRepo.observeUser("42").collect { user ->
        uiState = LoginUiState.Success(user)
    }
}

Phase 7:Compose 与 MVI 成熟(2020-2025)

在这里插入图片描述

Jetpack Compose 的出现,让 Android 进入“声明式 UI”时代,架构也朝着“MVI(Model-View-Intent)+状态机”收敛。

@Composable
fun LoginScreen(viewModel: LoginViewModel = hiltViewModel()) {
    val state by viewModel.state.collectAsState()

Column(modifier = Modifier.padding(16.dp)) {
        OutlinedTextField(
            value = state.email,
            onValueChange = viewModel::onEmailChange,
            label = { Text("Email") }
        )
        Button(
            onClick = viewModel::onLoginClick,
            enabled = !state.loading
        ) {
            if (state.loading) CircularProgressIndicator()
            else Text("Login")
        }
        state.error?.let { Text(it, color = Color.Red) }
        state.user?.let { Text("Welcome ${it.email}") }
    }
}

Compose 用 Kotlin 代码写 UI,通过“状态驱动渲染”替代了 XML 的命令式操作;MVI 则是单向数据流的极致实践:View 发送 Intent(用户操作),ViewModel 接收后更新 State(单一数据源),Compose 观察 State 自动重组 UI。

class LoginViewModel(
    private val authRepo: AuthRepository
) : ViewModel() {

private val _state = MutableStateFlow(LoginUiState())
    val state = _state.asStateFlow()
    fun onEmailChange(value: String) {
        _state.update { it.copy(email = value) }
    }
    fun onLoginClick() = viewModelScope.launch {
        _state.update { it.copy(loading = true, error = null) }
        runCatching { authRepo.login(_state.value.email, _state.value.password) }
            .onSuccess { user -> _state.update { it.copy(loading = false, user = user) } }
            .onFailure { e -> _state.update { it.copy(loading = false, error = e.message) } }
    }
}
data class LoginUiState(
    val email: String = "",
    val password: String = "",
    val loading: Boolean = false,
    val user: User? = null,
    val error: String? = null
)

同时,“状态机”成了复杂页面的标配——把页面状态(如“登录中→登录成功→个人主页”)定义为枚举,状态切换的逻辑显式写在 ViewModel 中,让状态变化完全可预测、可测试。如今,MVI+状态机+Compose 的组合,成了复杂 App 的“终局架构”:既保证了代码的简洁性,又让复杂逻辑的维护和测试变得轻松。

7 个阶段的核心逻辑

从 Phase 1 到 Phase 7,Android 架构的进化路径很清晰:从“功能优先”到“架构优先”,从“耦合混乱”到“分层解耦”,从“命令式编程”到“响应式+声明式编程”。每个阶段都是为了解决前一阶段的痛点——没有“最好的架构”,只有“适合当前业务的架构”:小 Demo 不用过度设计,大型 App 则需要 MVI+状态机的规范支撑。而贯穿始终的,是开发者对“写出更优雅代码”的追求。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐