6.1.1 配置变更数据保持什么是配置变更配置变更是指设备配置发生变化系统会重建 Activity/Fragment屏幕旋转语言切换深色模式切换键盘可用性变化配置变更的问题// 传统方式 - 配置变更导致数据丢失classMainActivity:AppCompatActivity(){privatevaruserData:User?nullprivatevarorderList:ListOrder?nulloverridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 从 Intent 或网络加载数据userDataloadUserData()orderListloadOrderList()updateUI(userData,orderList)}// 屏幕旋转时Activity 重建数据丢失// onCreate 再次执行需要重新加载数据}ViewModel 的解决方案// 使用 ViewModel - 配置变更时数据保持classMainActivity:AppCompatActivity(){privatevalviewModel:UserViewModelbyviewModels()overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// ViewModel 在配置变更时保持不变viewModel.userData.observe(this){user-updateUI(user)}viewModel.orderList.observe(this){orders-updateUI(orders)}}}classUserViewModel:ViewModel(){privateval_userDataMutableLiveDataUser()valuserData:LiveDataUser_userDataprivateval_orderListMutableLiveDataListOrder()valorderList:LiveDataListOrder_orderListinit{// 只在 ViewModel 首次创建时加载一次数据loadUserData()loadOrderList()}privatefunloadUserData(){viewModelScope.launch{valuseruserRepository.getUser()_userData.valueuser}}privatefunloadOrderList(){viewModelScope.launch{valordersorderRepository.getOrders()_orderList.valueorders}}}6.1.2 分离视图逻辑与业务逻辑传统方式的问题// 传统方式 - 视图逻辑与业务逻辑耦合classMainActivity:AppCompatActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 业务逻辑直接写在 Activity 中btnLogin.setOnClickListener{valusernameetUsername.text.toString()valpasswordetPassword.text.toString()if(username.isEmpty()){Toast.makeText(this,用户名不能为空,Toast.LENGTH_SHORT).show()returnsetOnClickListener}if(password.isEmpty()){Toast.makeText(this,密码不能为空,Toast.LENGTH_SHORT).show()returnsetOnClickListener}if(password.length6){Toast.makeText(this,密码至少 6 位,Toast.LENGTH_SHORT).show()returnsetOnClickListener}// 网络请求lifecycleScope.launch{try{valresultlogin(username,password)if(result.success){Toast.makeText(thisMainActivity,登录成功,Toast.LENGTH_SHORT).show()navigateToHome()}else{Toast.makeText(thisMainActivity,result.message,Toast.LENGTH_SHORT).show()}}catch(e:Exception){Toast.makeText(thisMainActivity,登录失败${e.message},Toast.LENGTH_SHORT).show()}}}}}ViewModel 的解决方案// 使用 ViewModel - 分离视图逻辑与业务逻辑classMainActivity:AppCompatActivity(){privatevalviewModel:LoginViewModelbyviewModels()overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)// 观察登录状态viewModel.loginState.observe(this){state-when(state){isLoginState.Idle-{// 初始状态}isLoginState.Loading-{showLoading()}isLoginState.Success-{hideLoading()navigateToHome()}isLoginState.Error-{hideLoading()showError(state.message)}}}// 视图逻辑btnLogin.setOnClickListener{valusernameetUsername.text.toString()valpasswordetPassword.text.toString()viewModel.login(username,password)}}}// ViewModel - 纯业务逻辑classLoginViewModel(privatevalloginRepository:LoginRepository):ViewModel(){privateval_loginStateMutableLiveDataLoginState()valloginState:LiveDataLoginState_loginStatefunlogin(username:String,password:String){// 业务逻辑if(username.isEmpty()){_loginState.valueLoginState.Error(用户名不能为空)return}if(password.isEmpty()){_loginState.valueLoginState.Error(密码不能为空)return}if(password.length6){_loginState.valueLoginState.Error(密码至少 6 位)return}// 网络请求viewModelScope.launch{_loginState.valueLoginState.Loadingtry{valresultloginRepository.login(username,password)if(result.success){_loginState.valueLoginState.Success(result.user)}else{_loginState.valueLoginState.Error(result.message)}}catch(e:Exception){_loginState.valueLoginState.Error(登录失败${e.message})}}}}// 登录状态sealedclassLoginState{objectIdle:LoginState()objectLoading:LoginState()dataclassSuccess(valuser:User):LoginState()dataclassError(valmessage:String):LoginState()}6.1.3 ViewModel 的生命周期ViewModel 的生命周期示意图Activity 生命周期 onCreate → ViewModel 创建 onStart onResume onPause onStop onDestroy (配置变更) → ViewModel 保持 onCreate → ViewModel 复用 onDestroy (真正销毁) → ViewModel 销毁 Fragment 生命周期 onAttach → ViewModel 创建 onCreate onCreateView onStart onResume onPause onStop onDestroyView → ViewModel 保持 onDestroy (配置变更) → ViewModel 保持 onDetach → ViewModel 销毁ViewModel 生命周期的特点特性说明创建时机Activity/Fragment 首次创建时销毁时机Activity/Fragment 真正销毁时非配置变更配置变更配置变更时 ViewModel 保持不变范围Activity/Fragment 的生命周期范围