You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android MVVM架构下屏幕旋转后Spinner选中状态异常重置问题

问题根因

你的代码逻辑方向正确,出现旋转后重置的问题基本是以下几个常见场景导致的:

  • 在Spinner的数据源businessPartners还未加载完成时就触发了setSelection,此时Spinner的adapter条目数为0,设置的选中位置不生效,等后续数据源加载完就会默认回到第0位
  • ViewModel实例获取方式错误,没有使用Activity范围的ViewModel,旋转后新建了ViewModel实例导致存储的spinnerString值丢失
  • spinnerString没有设置初始默认值,首次创建Activity时观察者回调拿到空值,设置不生效
  • 你设置OnItemSelectedListener的时机在观察者注册之前,首次设置setSelection的时候会触发onItemSelected回调,可能覆盖原有存储的值

修复步骤

1. 确认ViewModel实例获取方式正确

确保通过如下方式获取ViewModel,保证旋转后ViewModel不会重建:

// 不要使用ViewModelProvider.NewInstanceFactory()这类每次新建实例的方式
val dealMealPreApproval = ViewModelProvider(this)[MealPolicyViewModel::class.java]

2. 调整执行顺序,等数据源加载完成后再设置选中位置

你的Spinner数据源存储在ViewModel的businessPartners中,要先观察这个数据源,等它加载完成、给Spinner设置完Adapter之后,再执行setSelection操作:

// 先监听数据源变化,设置Spinner的Adapter
dealMealPreApproval.businessPartners.observe(this) { list ->
    val adapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, list)
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
    GetBusinessPartners.adapter = adapter
    // 数据源设置完成后再触发选中位置设置,此时才会生效
    dealMealPreApproval.getSpinnerValue().value?.let {
        GetBusinessPartners.setSelection(it)
    }
}

// 再设置选中监听
GetBusinessPartners.setOnItemSelectedListener(object:OnItemSelectedListener{
    override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        dealMealPreApproval.initsetSpinnerIndex(position)
    }
    override fun onNothingSelected(parent: AdapterView<*>?) = Unit
})

// 最后监听选中值变化,单独处理后续选中变更的场景
dealMealPreApproval.getSpinnerValue().observe(this) {
    // 增加防御判断,避免Spinner还没加载完就设置位置
    if (GetBusinessPartners.adapter != null && it < GetBusinessPartners.adapter.count) {
        GetBusinessPartners.setSelection(it)
    }
}

3. 给spinnerString设置初始默认值

在ViewModel初始化的时候直接给默认值,避免空值导致设置失效:

class MealPolicyViewModel : ViewModel() {
    var businessPartners = MutableLiveData<ArrayList<BusinessPartnersModel>>()
    // 直接初始化默认选中第0位,避免空值
    var spinnerString = MutableLiveData<Int>(0)

    fun initsetSpinnerIndex(valueOfSpinner:Int){
        // 增加值变更判断,避免相同值重复回调
        if (spinnerString.value != valueOfSpinner) {
            spinnerString.value = valueOfSpinner
            Log.d("valueOfValueOFSPinner",valueOfSpinner.toString())
        }
    }

    fun getSpinnerValue() : LiveData<Int>{
        return spinnerString
    }
}

内容的提问来源于stack exchange,提问作者Muhammad Umair

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 23:12:04