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
相关产品推荐
相关产品推荐

