xDocxDoc
AI
前端
后端
iOS
Android
Flutter
AI
前端
后端
iOS
Android
Flutter
  • Android 面试合集

    • Android面试基础篇(一):基础架构与核心组件深度剖析
    • Android中高级面试(二):架构组件与协程实战精要
    • Android中高级面试(三):架构组件与性能优化实战
    • Android 面试(四): Kotlin 基础
    • Android面试(五):深入Kotlin协程
    • Android面试(六):深入Kotlin Flow
    • Android面试(七):Jetpack Compose 深度解析与高频考点
    • Android架构面试(八):从Jetpack到模块化设计
    • Android架构面试(九):Clean Architecture 终极指南
    • Android面试全栈指南:从Kotlin到Jetpack Compose

Android中高级面试(二):架构组件与协程实战精要

🔍 一、ViewModel 架构组件深度剖析

1.1 ViewModel 的生命周期管理机制

class UserViewModel : ViewModel() {
    private val _userData = MutableLiveData<User>()
    val userData: LiveData<User> get() = _userData

    // 数据加载逻辑封装在ViewModel中
    fun loadUser(userId: String) {
        viewModelScope.launch {
            _userData.value = repository.fetchUser(userId)
        }
    }
}

// Activity/Fragment中的使用
class ProfileActivity : AppCompatActivity() {
    private val viewModel by viewModels<UserViewModel>()

    override fun onCreate(savedInstanceState: Bundle?) {
        viewModel.userData.observe(this) { user ->
            updateUI(user)
        }
    }
}

核心机制解析:
ViewModel 通过 ViewModelStore 实现与UI控制器的生命周期解耦,其存活周期从首次获取到Activity finish或Fragment detach。当设备旋转时,Activity重建但ViewModel实例保持不变,避免数据重复加载。

1.2 SavedStateHandle 的数据持久化

class SearchViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
    val query: MutableLiveData<String> = savedStateHandle.getLiveData("query_key")

    fun setQuery(query: String) {
        savedStateHandle["query_key"] = query
    }
}

// 获取实例时注入SavedStateHandle
val viewModel: SearchViewModel by viewModels {
    SavedStateViewModelFactory(application, this)
}

应用场景:
当进程因系统资源回收被杀时,SavedStateHandle 可自动恢复数据。其内部采用Bundle存储机制,支持基本数据类型及Parcelable对象。

🌊 二、LiveData 高级应用与陷阱规避

2.1 Transformations 操作符实战

val userIdLiveData = MutableLiveData<String>()
val userLiveData: LiveData<User> = Transformations.switchMap(userIdLiveData) { id ->
    repository.getUserById(id)
}

// 复合数据转换示例
val userProfile = Transformations.map(userLiveData) { user ->
    "${user.name} | ${user.email}"
}

2.2 避免LiveData的常见陷阱

内存泄漏防范:

// 错误示例:在Activity中使用匿名Observer
viewModel.data.observe(this) { data ->
    updateView(data)
    // 当Activity销毁时,此匿名Observer无法自动移除
}

// 正确方案:使用LifecycleOwner
class ProfileFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        viewModel.data.observe(viewLifecycleOwner) { data ->
            updateViews(data)
        }
    }
}

🚀 三、Kotlin协程在Android中的工程实践

3.1 结构化并发模型

class OrderViewModel : ViewModel() {
    private val _orderStatus = MutableLiveData<OrderStatus>()
    val orderStatus: LiveData<OrderStatus> get() = _orderStatus

    fun fetchOrderDetails(orderId: String) {
        viewModelScope.launch(Dispatchers.IO) {
            try {
                val order = repository.getOrder(orderId)
                withContext(Dispatchers.Main) {
                    _orderStatus.value = OrderStatus.Success(order)
                }
            } catch (e: Exception) {
                _orderStatus.value = OrderStatus.Error(e)
            }
        }
    }
}

并发控制技巧:

// 并行请求优化
suspend fun fetchDashboardData() = coroutineScope {
    val userDeferred = async { getUserData() }
    val notificationsDeferred = async { getNotifications() }
    
    val user = userDeferred.await()
    val notifications = notificationsDeferred.await()
    
    DashboardData(user, notifications)
}

3.2 协程与Room数据库的深度集成

@Dao
interface UserDao {
    @Query("SELECT * FROM users")
    fun getAllUsers(): Flow<List<User>>  // 使用Flow实现实时数据库监听

    @Insert
    suspend fun insertUser(user: User)  // 挂起函数保证线程安全
}

// ViewModel中使用
viewModelScope.launch {
    userDao.getAllUsers().collect { users ->
        _userList.value = users
    }
}

⚡ 四、性能优化与架构设计进阶

4.1 响应式UI架构设计

4.2 内存泄漏检测与防范

// 使用Android Profiler检测步骤:
// 1. 执行可能泄漏的操作(如旋转设备)
// 2. 触发GC
// 3. 检查Activity/Fragment实例是否仍被持有

// 使用LeakCanary自动检测
dependencies {
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
}

💡 五、高频面试题精析

5.1 ViewModel vs onSaveInstanceState

特性ViewModelonSaveInstanceState
数据存活范围直到Activity销毁进程被杀死后重建
数据类型限制支持复杂对象仅支持基本类型和Parcelable
适用场景屏幕旋转保持数据进程回收后恢复数据

5.2 LiveData与StateFlow对比

// LiveData示例
viewModel.data.observe(viewLifecycleOwner) { data ->
    updateUI(data)
}

// StateFlow示例
viewModel.uiState.collectLatest { state ->
    when (state) {
        is UiState.Loading -> showProgress()
        is UiState.Success -> showData(state.data)
        is UiState.Error -> showError(state.exception)
    }
}

总结

📚 核心要点回顾

  1. ViewModel架构优势

    • 生命周期感知的数据持有者
    • 配合SavedStateHandle实现进程回收恢复
    • 通过ViewModelProvider.Factory实现依赖注入
  2. LiveData高级用法

    • Transformations实现数据流转换
    • 配合LifecycleOwner避免内存泄漏
    • 与DataBinding的双向绑定集成
  3. 协程最佳实践

    • 结构化并发保障任务可管理
    • viewModelScope自动取消机制
    • Flow实现数据库实时监听
  4. 性能优化方向

    • 使用Profiler检测内存泄漏
    • 避免在ViewModel持有Context
    • 合理使用Dispatchers控制线程切换

面试实战建议:在解释技术原理时,务必结合具体业务场景。例如当被问到“如何保证数据在屏幕旋转时不丢失”,可回答:“采用ViewModel保存业务数据,同时使用SavedStateHandle处理进程回收场景,具体实现如代码示例中所示...”

最后更新: 2025/9/29 08:41
Prev
Android面试基础篇(一):基础架构与核心组件深度剖析
Next
Android中高级面试(三):架构组件与性能优化实战