6.2.1 ViewModel 的创建与获取方式1使用 by viewModels 委托推荐classMainActivity:AppCompatActivity(){// 使用 by viewModels 委托创建 ViewModelprivatevalviewModel:UserViewModelbyviewModels()overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)// 直接使用 viewModelviewModel.userData.observe(this){user-updateUI(user)}}}方式2使用 ViewModelProvider 手动创建classMainActivity:AppCompatActivity(){privatelateinitvarviewModel:UserViewModeloverridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)// 手动创建 ViewModelviewModelViewModelProvider(this)[UserViewModel::class.java]viewModel.userData.observe(this){user-updateUI(user)}}}方式3Fragment 中获取 Activity 的 ViewModelclassUserFragment:Fragment(){// 获取 Activity 的 ViewModel共享 ViewModelprivatevalviewModel:UserViewModelbyactivityViewModels()overridefunonViewCreated(view:View,savedInstanceState:Bundle?){super.onViewCreated(view,savedInstanceState)viewModel.userData.observe(viewLifecycleOwner){user-updateUI(user)}}}方式4:ViewModelProvider.Factory带参数的 ViewModel 创建// 定义带参数的 ViewModelclassUserViewModel(privatevaluserId:String,privatevalrepository:UserRepository):ViewModel(){privateval_userDataMutableLiveDataUser()valuserData:LiveDataUser_userDatainit{loadUserData()}privatefunloadUserData(){viewModelScope.launch{valuserrepository.getUser(userId)_userData.valueuser}}}// 定义 FactoryclassUserViewModelFactory(privatevaluserId:String,privatevalrepository:UserRepository):ViewModelProvider.Factory{overridefunT:ViewModelcreate(modelClass:ClassT):T{if(modelClass.isAssignableFrom(UserViewModel::class.java)){Suppress(UNCHECKED_CAST)returnUserViewModel(userId,repository)asT}throwIllegalArgumentException(Unknown ViewModel class)}}// 使用 Factory 创建 ViewModelclassMainActivity:AppCompatActivity(){privatevalviewModel:UserViewModelbyviewModels{UserViewModelFactory(userIdU001,repositoryUserRepository())}overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)viewModel.userData.observe(this){user-updateUI(user)}}}方式五使用 Hilt 依赖注入// 使用 Hilt 注入 ViewModelHiltViewModelclassUserViewModelInjectconstructor(privatevalrepository:UserRepository):ViewModel(){privateval_userDataMutableLiveDataUser()valuserData:LiveDataUser_userData}// 在 Activity 中使用AndroidEntryPointclassMainActivity:AppCompatActivity(){privatevalviewModel:UserViewModelbyviewModels()overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)viewModel.userData.observe(this){user-updateUI(user)}}}6.2.3 ViewModel 与 Fragment 共享数据场景Activity 和多个 Fragment 共享数据// ActivityclassMainActivity:AppCompatActivity(){privatevalviewModel:SharedViewModelbyviewModels()overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)// Activity 可以修改数据viewModel.updateUser(User(1,张三,zhangexample.com))}}// Fragment1classUserListFragment:Fragment(){// 获取 Activity 的 ViewModelprivatevalviewModel:SharedViewModelbyactivityViewModels()overridefunonViewCreated(view:View,savedInstanceState:Bundle?){super.onViewCreated(view,savedInstanceState)viewModel.userList.observe(viewLifecycleOwner){users-updateUI(users)}}}// Fragment2classUserDetailFragment:Fragment(){// 获取 Activity 的 ViewModelprivatevalviewModel:SharedViewModelbyactivityViewModels()overridefunonViewCreated(view:View,savedInstanceState:Bundle?){super.onViewCreated(view,savedInstanceState)viewModel.selectedUser.observe(viewLifecycleOwner){user-updateUI(user)}}}// 共享的 ViewModelclassSharedViewModel:ViewModel(){privateval_userListMutableLiveDataListUser()valuserList:LiveDataListUser_userListprivateval_selectedUserMutableLiveDataUser()valselectedUser:LiveDataUser_selectedUserfunupdateUser(user:User){_selectedUser.valueuser}funupdateUserList(users:ListUser){_userList.valueusers}}6.3.1 ViewModel 与协程集成 viewModelScopeviewModelScope - ViewModel 生命周期感知的协程作用域classUserViewModel(privatevalrepository:UserRepository):ViewModel(){privateval_userDataMutableLiveDataUser()valuserData:LiveDataUser_userDatainit{// 使用 viewModelScope 启动协程viewModelScope.launch{// 当 ViewModel 销毁时协程自动取消valuserrepository.getUser()_userData.valueuser}}funloadUser(userId:String){viewModelScope.launch{valuserrepository.getUser(userId)_userData.valueuser}}overridefunonCleared(){super.onCleared()// ViewModel 销毁时viewModelScope 中的所有协程自动取消println(ViewModel 销毁协程已取消)}}viewModelScope 的特性特性说明生命周期与 ViewModel 绑定自动取消ViewModel 销毁时自动取消协程调度器默认使用 Dispatchers.Main.immediate异常处理未捕获的异常会传播到父协程6.3.2 协程取消机制协程取消的示例classUserViewModel(privatevalrepository:UserRepository):ViewModel(){privateval_userDataMutableLiveDataUser()valuserData:LiveDataUser_userDataprivateval_loadingMutableLiveDataBoolean()valloading:LiveDataBoolean_loadingfunloadUser(userId:String){viewModelScope.launch{_loading.valuetruetry{// 如果 ViewModel 销毁这里会抛出 CancellationExceptionvaluserrepository.getUser(userId)_userData.valueuser}catch(e:Exception){if(e!isCancellationException){// 处理业务异常忽略取消异常println(加载用户失败${e.message})}}finally{_loading.valuefalse}}}overridefunonCleared(){super.onCleared()// 所有 viewModelScope 中的协程会被取消}}使用 SupervisorJob 避免子协程相互影响classUserViewModel(privatevalrepository:UserRepository):ViewModel(){privateval_userDataMutableLiveDataUser()valuserData:LiveDataUser_userDataprivateval_orderListMutableLiveDataListOrder()valorderList:LiveDataListOrder_orderListfunloadAllData(userId:String){viewModelScope.launch{// 使用 SupervisorJob子协程失败不影响其他子协程valuserDeferredasync{repository.getUser(userId)}valordersDeferredasync{repository.getOrders(userId)}try{valuseruserDeferred.await()_userData.valueuser}catch(e:Exception){println(加载用户失败${e.message})}try{valordersordersDeferred.await()_orderList.valueorders}catch(e:Exception){println(加载订单失败${e.message})}}}}7.3.1 map 转换map - 转换 LiveData 的数据类型classUserViewModel:ViewModel(){privateval_userDataMutableLiveDataUser()valuserData:LiveDataUser_userData// 使用 map 转换数据valuserName:LiveDataString_userData.map{user-user.name}valuserEmail:LiveDataString_userData.map{user-user.email}valuserGreeting:LiveDataString_userData.map{user-你好${user.name}}funloadUser(){viewModelScope.launch{valuseruserRepository.getUser()_userData.valueuser}}}###7.3.2switchMap 转换**switchMap-动态切换 LiveData** kotlinclassUserViewModel(privatevalrepository:UserRepository):ViewModel(){privateval_userIdMutableLiveDataString()valuserId:LiveDataString_userId// 使用 switchMap 动态切换 LiveDatavaluserData:LiveDataUser_userId.switchMap{userId-repository.getUserLiveData(userId)}funloadUser(userId:String){_userId.valueuserId}}**switchMap vs map 对比** | 特性 | map | switchMap | |------|-----|-----------| |**转换类型**| 数据类型转换 | LiveData 切换 | |**触发条件**| 源 LiveData 更新时 | 源 LiveData 更新时 | |**返回值**| 单个值 | 新的 LiveData | |**使用场景**| 简单的数据转换 | 动态数据加载 | ###7.3.3MediatorLiveData 合并多个数据源**MediatorLiveData-合并多个 LiveData** kotlinclassUserViewModel:ViewModel(){privateval_userDataMutableLiveDataUser()valuserData:LiveDataUser_userDataprivateval_orderDataMutableLiveDataListOrder()valorderData:LiveDataListOrder_orderDataprivateval_productDataMutableLiveDataListProduct()valproductData:LiveDataListProduct_productData// 合并多个 LiveDataprivateval_dashboardDataMediatorLiveDataDashboardData()valdashboardData:LiveDataDashboardData_dashboardDatainit{// 添加源 LiveData_dashboardData.addSource(_userData){user-updateDashboardData()}_dashboardData.addSource(_orderData){orders-updateDashboardData()}_dashboardData.addSource(_productData){products-updateDashboardData()}}privatefunupdateDashboardData(){valuser_userData.valuevalorders_orderData.value?:emptyList()valproducts_productData.value?:emptyList()_dashboardData.valueDashboardData(useruser,orderCountorders.size,productCountproducts.size)}funloadDashboard(){viewModelScope.launch{valuseruserRepository.getUser()_userData.valueuservalordersorderRepository.getOrders()_orderData.valueordersvalproductsproductRepository.getProducts()_productData.valueproducts}}}dataclassDashboardData(valuser:User?,valorderCount:Int,valproductCount:Int)7.4.3 使用 SharedFlow 替代 LiveData见第21章SharedFlow vs LiveData// SharedFlow - 更现代的响应式组件classMyViewModel:ViewModel(){// SharedFlow 支持多个观察者privateval_eventsMutableSharedFlowEvent()valevents:SharedFlowEvent_events.asSharedFlow()funsendEvent(event:Event){viewModelScope.launch{_events.emit(event)}}}// 使用classMainActivity:AppCompatActivity(){privatevalviewModel:MyViewModelbyviewModels()overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)lifecycleScope.launch{viewModel.events.collect{event-handleEvent(event)}}}}核心要点回顾ViewModel 的设计理念配置变更数据保持分离视图逻辑与业务逻辑ViewModel 的生命周期ViewModel 基础用法ViewModel 的创建与获取ViewModelProvider.FactoryViewModel 与 Fragment 共享数据ViewModel 与协程集成viewModelScope 的使用协程取消机制SupervisorJob 的使用LiveData 转换操作map 转换switchMap 动态切换MediatorLiveData 合并多个数据源