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

Android Kotlin SearchView输入时lateinit property adapter未初始化报错

报错原因
  • 类顶部声明的全局lateinit var adapter从未被赋值,你在onCreate方法中创建的customAdapter是局部变量,和全局的adapter没有关联,触发搜索逻辑调用adapter.filter时就会抛出未初始化异常
  • 额外问题1:onCreate中var listView = findViewById<ListView>(R.id.listV)同样是重复声明的局部变量,全局声明的listView也未初始化,后续调用全局listView时也会报错
  • 额外问题2:你自定义的CustomAdapter继承自BaseAdapter,默认没有实现Filterable接口,即使给adapter赋值后直接调用filter也无法实现搜索功能
  • 额外问题3:你注释了setSupportActionBar(toolbar)代码,会导致Toolbar的搜索菜单无法正常加载
修复步骤

1. 修正全局变量赋值

首先修改类顶部的adapter声明,适配自定义的适配器类型:

// 把原来的 lateinit var adapter: ArrayAdapter<*> 改成下面的
lateinit var adapter: CustomAdapter

然后修改onCreate中的变量赋值逻辑,去掉重复的局部变量声明,给全局变量赋值:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.list_vw)

    toolbar = findViewById(R.id.toolbar)
    // 打开注释,设置Toolbar为ActionBar
    setSupportActionBar(toolbar);
    emptyView = findViewById(R.id.emptyView)
    // 去掉var,直接给全局listView赋值
    listView = findViewById<ListView>(R.id.listV)

    // 创建适配器,给全局adapter赋值
    val customAdapter = CustomAdapter(this)
    adapter = customAdapter
    listView.adapter = adapter

    listView.setOnItemClickListener{ parent, view, position, id ->
        Toast.makeText(this, "You Clicked: " + adapter.filteredNames[position],Toast.LENGTH_SHORT).show()
        var intent = Intent(applicationContext,NextPage::class.java)
        startActivity(intent)
    }
    listView.emptyView = emptyView
}

2. 给CustomAdapter实现Filterable接口,添加搜索过滤逻辑

修改CustomAdapter代码,实现过滤功能:

class CustomAdapter(private val context:Activity):BaseAdapter(), Filterable {
    // 原始不变的数据源
    private val originalNames = arrayOf("Apple","Strawberry","Bannana","Peach","Cocout")
    private val originalDesc = arrayOf("Red and round","Red","Yellow","Pink","Green")
    private val originalImage = intArrayOf(R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground,R.drawable.ic_launcher_foreground)

    // 过滤后展示的动态数据源
    var filteredNames = originalNames.toMutableList()
    var filteredDesc = originalDesc.toMutableList()
    var filteredImage = originalImage.toMutableList()

    override fun getCount(): Int {
        return filteredNames.size
    }

    override fun getItem(position: Int): Any {
        return filteredImage[position]
    }

    override fun getItemId(position: Int): Long {
        return filteredImage[position].toLong()
    }

    override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
        val inflater= context.layoutInflater
        val view1= inflater.inflate(R.layout.custom_list,null)

        val fName= view1.findViewById<TextView>(R.id.fName)
        val fDesc= view1.findViewById<TextView>(R.id.fDescp)
        val fImage= view1.findViewById<ImageView>(R.id.fImage)

        fName.text = filteredNames[position]
        fDesc.text = filteredDesc[position]
        fImage.setImageResource(filteredImage[position])
        return view1
    }

    // 实现过滤逻辑
    override fun getFilter(): Filter {
        return object : Filter() {
            override fun performFiltering(constraint: CharSequence?): FilterResults {
                val query = constraint?.toString()?.trim()?.lowercase() ?: ""
                val results = FilterResults()
                if (query.isEmpty()) {
                    // 搜索词为空,返回全部原始数据
                    results.values = Triple(originalNames.toList(), originalDesc.toList(), originalImage.toList())
                    results.count = originalNames.size
                } else {
                    val matchedNames = mutableListOf<String>()
                    val matchedDesc = mutableListOf<String>()
                    val matchedImage = mutableListOf<Int>()
                    // 匹配名称或描述包含搜索词的条目
                    for (i in originalNames.indices) {
                        if (originalNames[i].lowercase().contains(query) 
                            || originalDesc[i].lowercase().contains(query)) {
                            matchedNames.add(originalNames[i])
                            matchedDesc.add(originalDesc[i])
                            matchedImage.add(originalImage[i])
                        }
                    }
                    results.values = Triple(matchedNames, matchedDesc, matchedImage)
                    results.count = matchedNames.size
                }
                return results
            }

            override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
                results?.let {
                    val data = it.values as Triple<List<String>, List<String>, List<Int>>
                    filteredNames = data.first.toMutableList()
                    filteredDesc = data.second.toMutableList()
                    filteredImage = data.third.toMutableList()
                    // 刷新列表展示
                    notifyDataSetChanged()
                }
            }
        }
    }
}

修改完成后即可正常实现搜索功能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:24:04