如何将EditText中的年龄变量存入ViewModel并实现屏幕旋转时保留?
解决方案
一、修正ViewModel,用SavedStateHandle持久化年龄
你的ViewModel已经注入了SavedStateHandle,但没有实际用它存储年龄变量,所以屏幕旋转后数据丢失。修改ViewModel代码如下:
private const val TAG = "age" private const val KEY_SAVED_AGE = "saved_age" // 定义存储用的唯一Key class HrViewModel(private val state: SavedStateHandle) : ViewModel() { // 封装SavedStateHandle的读写逻辑 private var savedAge: Int get() = state.get(KEY_SAVED_AGE) ?: 0 set(value) = state.set(KEY_SAVED_AGE, value) // 更新并保存年龄 fun updateAge(newAge: Int) { savedAge = newAge } // 获取保存的年龄(供Activity恢复UI用) fun getSavedAge(): Int = savedAge fun calculateMaxHr(): Int { return 220 - savedAge } fun concatenate(vararg digits: Int): String { return digits.joinToString(separator = " - ", transform = Int::toString) } fun getTargetHrRange(): String { val maxHr = calculateMaxHr() val low = (maxHr * 0.5).toInt() val high = (maxHr * 0.85).toInt() return concatenate(low, high) } }
二、在MainActivity中传递年龄到ViewModel
不需要在Activity里直接操作SavedStateHandle,ViewModel内部会负责存储逻辑。当你从EditText获取到年龄后,调用ViewModel的updateAge方法即可:
// 示例:点击计算按钮时的逻辑 binding.calculateBtn.setOnClickListener { val inputAge = binding.age.text.toString().toIntOrNull() ?: 0 hrViewModel.updateAge(inputAge) // 同步显示计算结果 binding.targetRangeTv.text = hrViewModel.getTargetHrRange() }
三、屏幕旋转后恢复数据
ViewModel会在配置变更(如屏幕旋转)时自动保留,SavedStateHandle中的数据也会被恢复。Activity重建后,直接从ViewModel读取保存的年龄并恢复UI:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) val hrViewModel = ViewModelProvider(this)[HrViewModel::class.java] // 恢复之前保存的年龄到EditText val storedAge = hrViewModel.getSavedAge() if (storedAge != 0) { binding.age.setText(storedAge.toString()) binding.targetRangeTv.text = hrViewModel.getTargetHrRange() } // 绑定按钮点击逻辑... }
四、关于OnResume的疑问
不需要把逻辑放在OnResume里。ViewModel的生命周期跨越Activity配置变更,SavedStateHandle会自动处理数据的持久化与恢复,只要你在ViewModel中正确封装读写逻辑,Activity重建时直接从ViewModel取数据即可。
内容的提问来源于stack exchange,提问作者Nikki
相关产品推荐
相关产品推荐

