Android架构面试(八):从Jetpack到模块化设计
🔍 现代Android架构演进史
从早期传统的MVC模式到如今主流的分层架构设计,Android架构经历了三次重大变革:
- 原始时代(2015前):Activity/Fragment承担所有逻辑,导致"God Activity"问题
// 典型反例:所有逻辑堆砌在Activity中
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
// UI初始化、网络请求、数据处理全部混杂
val data = loadDataFromNetwork() // 阻塞主线程
updateUI(data)
saveToDatabase(data)
}
}
架构组件革命(2017):Google推出Android Architecture Components
- ViewModel:解决配置变更数据丢失
- LiveData:生命周期感知的数据持有者
- Room:SQLite对象映射库
现代架构(2020+):引入单向数据流(Unidirectional Data Flow)和响应式编程
🧩 核心架构组件深度解析
1. ViewModel 的生命周期管理
class UserViewModel(private val repo: UserRepository) : ViewModel() {
private val _userData = MutableStateFlow<User?>(null)
val userData: StateFlow<User?> = _userData.asStateFlow()
init {
viewModelScope.launch {
repo.fetchUser().collect { user ->
_userData.value = user
}
}
}
}
// 关键特性:
// 1. 使用viewModelScope自动取消协程
// 2. StateFlow替代LiveData实现更纯粹的状态管理
2. LiveData vs Flow 性能对比
特性 | LiveData | Kotlin Flow |
---|---|---|
生命周期感知 | ✅ 原生支持 | ❌ 需配合LifecycleScope |
背压处理 | ❌ | ✅ 丰富操作符 |
线程控制 | ❌ 主线程限定 | ✅ 灵活调度器 |
数据重放 | ✅ 最新数据 | ✅ 可配置重放数量 |
3. Room数据库高级实践
@Dao
interface UserDao {
@Query("SELECT * FROM user WHERE region = :region")
fun getUsersByRegion(region: String): Flow<List<User>>
@Transaction // 支持复杂事务
@Query("UPDATE user SET status = :status WHERE id = :userId")
suspend fun updateUserStatus(userId: String, status: Int)
}
// 使用技巧:
// 1. 结合Flow实现数据库变化实时监听
// 2. 使用@Transaction确保多表操作原子性
🚀 主流架构模式实战
MVVM 最佳实践
// 分层结构示例
class LoginViewModel(
private val authRepo: AuthRepository
) : ViewModel() {
// UI状态集中管理
data class LoginState(
val isLoading: Boolean = false,
val error: String? = null,
val isSuccess: Boolean = false
)
private val _state = MutableStateFlow(LoginState())
val state: StateFlow<LoginState> = _state.asStateFlow()
fun login(username: String, password: String) {
viewModelScope.llaunch {
_state.value = LoginState(isLoading = true)
try {
authRepo.login(username, password)
_state.value = LoginState(isSuccess = true)
} catch (e: Exception) {
_state.value = LoginState(error = e.message)
}
}
}
}
MVI 模式实现
sealed class MainIntent {
object LoadData : MainIntent()
data class UpdateItem(val id: String) : MainIntent()
}
data class MainState(
val items: List<Item> = emptyList(),
val isLoading: Boolean = false
)
class MainViewModel : ViewModel() {
private val _state = MutableStateFlow(MainState())
val state: StateFlow<MainState> = _state.asStateFlow()
fun processIntent(intent: MainIntent) {
when (intent) {
is MainIntent.LoadData -> loadData()
is MainIntent.UpdateItem -> updateItem(intent.id)
}
}
}
📦 模块化架构设计
分层模块划分
app/
├── feature-auth/ // 认证模块
├── feature-home/ // 首页模块
├── feature-profile/ // 个人中心
├── core-network/ // 网络核心
├── core-database/ // 数据库核心
└── core-ui/ // UI组件库
模块间通信方案
// 使用Hilt依赖注入实现模块解耦
@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
@Provides
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create())
.build()
}
}
// 在feature模块中使用
@AndroidEntryPoint
class UserRepository @Inject constructor(
private val apiService: ApiService
) { /* ... */ }
🧪 架构测试策略
ViewModel单元测试
@Test
fun `login should update state on success`() = runTest {
// 1. 创建测试依赖
val mockRepo = mockk<AuthRepository>()
coEvery { mockRepo.login(any(), any()) } returns Unit
// 2. 创建ViewModel
val vm = LoginViewModel(mockRepo)
// 3. 执行操作
vm.login("test", "password")
// 4. 验证状态变化
val state = vm.state.first { !it.isLoading }
assertTrue(state.isSuccess)
}
UI层测试方案
@HiltAndroidTest
class LoginScreenTest {
@get:Rule
val hiltRule = HiltAndroidRule(this)
@Test
fun display_error_when_login_fails() {
// 1. 启动Compose测试
composeTestRule.setContent {
AppTheme { LoginScreen() }
}
// 2. 模拟错误状态
val vm = hiltNavGraphViewModel<LoginViewModel>()
vm.updateState(LoginState(error = "Invalid credentials"))
// 3. 验证UI显示
composeTestRule.onNodeWithText("Invalid credentials").assertIsDisplayed()
}
}
💡 性能优化关键点
内存优化
// 使用WeakReference避免内存泄漏 class ImageLoader(context: Context) { private val weakContext = WeakReference(context) fun load(url: String) { weakContext.get()?.let { // 加载图片 } } }
启动速度优化
<!-- 启动主题优化 --> <style name="LaunchTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowBackground">@drawable/launch_screen</item> </style>
网络请求优化
// 使用OkHttp拦截器实现请求缓存 val client = OkHttpClient.Builder() .addInterceptor(CacheInterceptor()) .cache(Cache(directory, 10 * 1024 * 1024)) // 10MB缓存 .build()
🌟 架构趋势
Kotlin Multiplatform 跨平台架构
// 共享业务逻辑模块 class SharedViewModel { fun businessLogic(): String { return "Core Logic" } } // Android端调用 class AndroidViewModel : ViewModel() { private val shared = SharedViewModel() val data = shared.businessLogic() }
Jetpack Compose 声明式UI架构
@Composable fun UserProfile(user: User) { Column { AsyncImage(model = user.avatarUrl) Text(text = user.name, style = MaterialTheme.typography.h5) // 状态提升示例 var expanded by remember { mutableStateOf(false) } IconButton(onClick = { expanded = !expanded }) { Icon(Icons.Default.MoreVert) } } }
AppStartup优化冷启动
<!-- 初始化配置优化 --> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false"> <meta-data android:name="com.example.LibraryInitializer" android:value="androidx.startup" /> </provider>
🚨 常见架构陷阱
ViewModel滥用
// 错误示范:在ViewModel中持有Context class WrongViewModel(context: Context) : ViewModel() { // Context可能导致内存泄漏 }
过度抽象
// 不必要的接口抽象 interface UserRepository { fun getUser(): User } class UserRepositoryImpl : UserRepository { override fun getUser(): User { ... } } // 直接使用具体类更简洁 class UserRepository { fun getUser(): User { ... } }
忽视线程安全
class UnsafeRepository { var data: List<Item> = emptyList() fun updateData() { // 多线程访问可能导致并发问题 data = fetchData() } }
📝 总结
核心原则
- 单一职责:每个组件/类只做一件事
- 可测试性:依赖注入使测试更简单
- 生命周期感知:自动管理资源释放
- 单向数据流:保证状态可预测
技术选型
场景 | 推荐方案 |
---|---|
状态管理 | StateFlow + ViewModel |
异步操作 | Kotlin协程 |
本地存储 | Room + Flow |
依赖注入 | Hilt |
UI框架 | Jetpack Compose |
性能指标
{
type: 'radar',
data: {
labels: ['启动时间', '内存占用', '帧率', '耗电量', '网络请求'],
datasets: [{
label: '架构优化前',
data: [65, 59, 80, 81, 75],
fill: true,
backgroundColor: 'rgba(255, 99, 132, 0.2)'
}, {
label: '架构优化后',
data: [85, 75, 95, 79, 92],
fill: true,
backgroundColor: 'rgba(75, 192, 192, 0.2)'
}]
}
}
总结
📚 架构设计核心要点
现代Android架构设计已形成以分层解耦为基础、响应式编程为手段、单向数据流为指导原则的标准范式。关键演进体现在:
- 关注点分离:Activity/Fragment仅处理UI逻辑,业务逻辑移至ViewModel
- 生命周期感知:LiveData/Flow自动管理订阅,避免内存泄漏
- 异步处理革命:协程替代Callback/RxJava简化异步代码
- 声明式UI:Compose推动UI开发范式转变
🛠️ 建议
- 渐进式改造:从新模块开始采用新架构,逐步重构旧代码
- 模块化先行:先划分功能模块再实施具体架构模式
- 测试驱动:编写ViewModel单元测试保障核心逻辑
- 性能监控:集成Profiler持续监控内存/CPU使用