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

Android 8.0中使用Kotlin创建的ArrayList数据源Spinner无法触发OnItemSelected事件及更新问题

Spinner绑定ArrayList数据源后无法触发OnItemSelected及更新显示的解决方案

问题场景

我在用Kotlin开发Android 8.0应用时碰到了Spinner的异常问题:

  • 一个通过资源字符串数组创建的Spinner工作完全正常;
  • 另一个以ArrayList作为数据源的Spinner,点击列表项时完全无法触发OnItemSelected回调,也不能更新自身的显示状态。

以下是我最初的错误实现代码:

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val modules = ArrayList<Module>()
        val bufferedReader = BufferedReader(InputStreamReader(resources.openRawResource(R.raw.mod_code)))
        var line = bufferedReader.readLine()
        while(line != null) {
            val values = line.split(",")
            modules.add(Module(values[0].replace("", "").toInt(), values[1], values[2].replace("", "").toDouble()))
            line = bufferedReader.readLine()
        }
        val moduleCodeArray = ArrayList<String>()
        val yearSpinner: Spinner = findViewById(R.id.year)
        yearSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                val item = parent?.getItemAtPosition(position).toString()
                Toast.makeText(parent?.context, "Selected: $item", Toast.LENGTH_LONG).show()
                moduleCodeArray.clear()
                for(module in modules) {
                    if(module.year == position + 1) {
                        moduleCodeArray.add(module.moduleCode)
                    }
                }
            }
            override fun onNothingSelected(parent: AdapterView<*>?) {
            }
        }
        ArrayAdapter.createFromResource(
            this,
            R.array.years,
            R.layout.custom_spinner
        ).also { adapter ->
            adapter.setDropDownViewResource(R.layout.custom_spinner_dropdown)
            yearSpinner.adapter = adapter
        }
        println(moduleCodeArray)
        val moduleCodeSpinner = findViewById<Spinner>(R.id.module_code)
        moduleCodeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                val item = parent?.getItemAtPosition(position).toString()
                Toast.makeText(parent?.context, "Selected: $item", Toast.LENGTH_LONG).show()
            }
            override fun onNothingSelected(parent: AdapterView<*>?) {}
        }
        ArrayAdapter(
            this,
            R.layout.custom_spinner,
            moduleCodeArray
        ).also { adapter ->
            adapter.setDropDownViewResource(R.layout.custom_spinner_dropdown)
            moduleCodeSpinner.adapter = adapter
        }
    }
}

问题根源

核心问题在于数据更新与适配器绑定的时机不匹配:
moduleCodeArray是在yearSpinner的OnItemSelected回调中才被填充数据的,但我最初在onCreate方法里就一次性创建了适配器并绑定到moduleCodeSpinner。此时moduleCodeArray是空的,后续回调中更新数组内容后,旧的适配器完全感知不到数据变化,也没有重新绑定新的数据源,最终导致Spinner既无法更新显示,也无法响应选中事件。

解决思路

把ArrayAdapter的创建与绑定逻辑,移到yearSpinner的OnItemSelected回调内部。这样每次选中年份后,都会基于更新后的moduleCodeArray创建新的适配器并绑定到moduleCodeSpinner,确保Spinner能获取到最新的数据源,同时正常响应选中事件。

修正后的正确代码

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val modules = ArrayList<Module>()
        val bufferedReader = BufferedReader(InputStreamReader(resources.openRawResource(R.raw.mod_code)))
        var line = bufferedReader.readLine()
        while(line != null) {
            val values = line.split(",")
            modules.add(Module(values[0].replace("", "").toInt(), values[1], values[2].replace("", "").toDouble()))
            line = bufferedReader.readLine()
        }
        
        val moduleCodeArray = ArrayList<String>()
        val moduleCodeSpinner = findViewById<Spinner>(R.id.module_code)
        val yearSpinner: Spinner = findViewById(R.id.year)
        
        yearSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener{
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                val item = parent?.getItemAtPosition(position).toString()
                Toast.makeText(parent?.context, "Selected: $item", Toast.LENGTH_LONG).show()
                
                moduleCodeArray.clear()
                for(module in modules) {
                    if(module.year == position + 1) {
                        moduleCodeArray.add(module.moduleCode)
                    }
                }
                
                // 将适配器的创建与绑定移到这里,确保每次数据更新后都重新绑定
                ArrayAdapter(
                    applicationContext,
                    R.layout.custom_spinner,
                    moduleCodeArray
                ).also { adapter ->
                    adapter.setDropDownViewResource(R.layout.custom_spinner_dropdown)
                    moduleCodeSpinner.adapter = adapter
                }
            }
            override fun onNothingSelected(parent: AdapterView<*>?) {
            }
        }
        
        ArrayAdapter.createFromResource(
            this,
            R.array.years,
            R.layout.custom_spinner
        ).also { adapter ->
            adapter.setDropDownViewResource(R.layout.custom_spinner_dropdown)
            yearSpinner.adapter = adapter
        }
        
        moduleCodeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
            override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
                val item = parent?.getItemAtPosition(position).toString()
                Toast.makeText(parent?.context, "Selected: $item", Toast.LENGTH_LONG).show()
            }
            override fun onNothingSelected(parent: AdapterView<*>?) {}
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:42:29