带自定义属性的Android货币切换视图返回Fragment后状态重置如何解决
问题原因
- 当前状态保存逻辑仅处理了子View的状态存储,没有存储
SwitchableTextField自身的三个自定义状态变量(defaultCurrency、conversionCurrency、conversionDirection),页面重建时这三个变量会被构造方法内的applyUserAttributes重置为XML配置的初始值。 - Android View重建流程为:先执行构造方法调用
applyUserAttributes加载初始属性,再执行onRestoreInstanceState恢复保存的状态,只需将自定义变量加入状态保存恢复逻辑,即可用恢复的正确值覆盖初始值解决问题。
修改方案
1. 扩展SavedState类,新增自定义状态的存储逻辑
internal class SavedState : AbsSavedState { internal var childrenStates: SparseArray<Parcelable>? = null // 新增三个自定义状态字段 internal var defaultCurrency: String? = null internal var conversionCurrency: String? = null internal var conversionDirection: Boolean = false constructor(superState: Parcelable?) : super(superState) @Suppress("UNCHECKED_CAST") constructor(source: Parcel) : super(source) { childrenStates = source.readSparseArray(javaClass.classLoader) // 读取保存的自定义状态 defaultCurrency = source.readString() conversionCurrency = source.readString() conversionDirection = source.readByte() != 0.toByte() } @Suppress("UNCHECKED_CAST") override fun writeToParcel(out: Parcel, flags: Int) { super.writeToParcel(out, flags) out.writeSparseArray(childrenStates as SparseArray<Any>) // 写入自定义状态 out.writeString(defaultCurrency) out.writeString(conversionCurrency) out.writeByte(if (conversionDirection) 1 else 0) } companion object { @Suppress("UNUSED") @JvmField val CREATOR = object : Parcelable.Creator<SavedState> { override fun createFromParcel(source: Parcel) = SavedState(source) override fun newArray(size: Int): Array<SavedState?> = arrayOfNulls(size) } } }
2. 修改onSaveInstanceState,存储当前自定义状态
override fun onSaveInstanceState(): Parcelable? { return SavedState(super.onSaveInstanceState()).apply { childrenStates = saveChildViewStates() // 保存当前自定义状态 defaultCurrency = this@SwitchableTextField.defaultCurrency conversionCurrency = this@SwitchableTextField.conversionCurrency conversionDirection = this@SwitchableTextField.conversionDirection } }
3. 修改onRestoreInstanceState,恢复自定义状态并刷新UI
public override fun onRestoreInstanceState(state: Parcelable?) { when (state) { is SavedState -> { super.onRestoreInstanceState(state.superState) state.childrenStates?.let { restoreChildViewStates(it) } // 恢复自定义状态,自动覆盖构造方法设置的初始值 state.defaultCurrency?.let { defaultCurrency = it } state.conversionCurrency?.let { conversionCurrency = it } conversionDirection = state.conversionDirection // 重新触发金额换算,保证显示结果正确 convertAmount(mainAmount) } else -> super.onRestoreInstanceState(state) } }
内容的提问来源于stack exchange,提问作者Maxime Michel
相关产品推荐
相关产品推荐

