在RecyclerView列表中使用SearchView时应用崩溃,求排查解决
问题:SearchView导致应用启动失败,无法实现披萨餐厅搜索功能
我开发的应用用RecyclerView展示披萨餐厅信息(名称、位置、评分),想加SearchView按名称搜索,但每次运行都报SearchView相关错误,应用启动不了。查了官方文档和教程,反复检查代码还是解决不了。
以下是我的RV.Adapter代码:
class PizzaAdapter(private var PizzaList: List<Pizza>): RecyclerView.Adapter<PizzaAdapter.PizzaViewHolder>() { private lateinit var listener: PizzaAdapterListener inner class PizzaViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val textViewName: TextView = itemView.findViewById(R.id.textViewName) val textViewLocation: TextView = itemView.findViewById(R.id.textViewLocation) val ratingBar: RatingBar = itemView.findViewById(R.id.ratingBar) } // end MyViewHolder override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PizzaViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.activity_current_pizza_palor_list, parent, false) return PizzaViewHolder(view) } override fun onBindViewHolder(holder: PizzaViewHolder, position: Int) { val pizza = PizzaList[position] holder.textViewName.text = pizza.name holder.textViewLocation.text = pizza.location holder.ratingBar.rating = pizza.rate!!?.toFloat()!! } override fun getItemCount(): Int { return PizzaList.size } fun setData(list: List<Pizza>) { PizzaList = list notifyDataSetChanged() } interface PizzaAdapterListener { fun onClick(position: Int) } fun getFilter(): Filter { return object : Filter() { override fun performFiltering(constraint: CharSequence?): FilterResults { val filteredList = mutableListOf<Pizza>() if (constraint == null || constraint.isEmpty()) { filteredList.addAll(PizzaList) } else { val filterPattern = constraint.toString().toLowerCase().trim() for (item in PizzaList) { if (item.name.toLowerCase().contains(filterPattern)) { filteredList.add(item) } } } val results = FilterResults() results.values = filteredList return results } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { PizzaList = results?.values as List<Pizza> notifyDataSetChanged() } fun setOnItemClickListener(_listener: PizzaAdapterListener) { listener = _listener } } } }
以下是使用SearchView的MainActivity代码:
class MainActivity : AppCompatActivity() { private lateinit var recyclerViewPizza: RecyclerView private lateinit var data : ArrayList<Pizza> private lateinit var pizzaAdapter : PizzaAdapter private lateinit var searchView : SearchView @SuppressLint("MissingInflatedId") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerViewPizza = findViewById<RecyclerView>(R.id.recyclerViewPizza) recyclerViewPizza.layoutManager = LinearLayoutManager(this) data = ArrayList<Pizza>() data.add(Pizza("Pizza Hut", "Deer Park", 3.1)) data.add(Pizza("Papa Johns", "Deer Park", 3.9)) data.add(Pizza("Richie's Pizza", "Commack", 4.4)) data.add(Pizza("Domino's Pizza", "Deer Park", 4.2)) val searchView = findViewById<SearchView>(R.id.searchView) searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { return false } override fun onQueryTextChange(newText: String?): Boolean { filter(newText) return true } }) } private fun filter(query: String?) { val filteredList = mutableListOf<Pizza>() if (query.isNullOrEmpty()) { filteredList.addAll(data) } else { val filterPattern = query.trim() for (item in data) { if (item.name.contains(filterPattern, true)) { filteredList.add(item) } } } } override fun onCreateOptionsMenu(menu: Menu?): Boolean { val inflater = menuInflater inflater.inflate(R.menu.toolmenu, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.getItemId()) { R.id.add_item->{ val intent = Intent(this@MainActivity, AddActivity::class.java) startActivity(intent) true } else -> super.onOptionsItemSelected(item) } } }
错误排查与修复方案
1. PizzaAdapter代码语法错误(直接导致启动失败)
getFilter()方法未正确闭合:publishResults方法结束后缺少},导致setOnItemClickListener被嵌套在Filter内部,触发语法错误。ratingBar.rating = pizza.rate!!?.toFloat()!!存在冗余空安全操作,!!?是无效语法,替换为pizza.rate?.toFloat() ?: 0f(兼容rate为null的情况)。- 将
PizzaList声明为MutableList<Pizza>,避免过滤时的类型转换异常。
修复后的PizzaAdapter:
class PizzaAdapter(private var pizzaList: MutableList<Pizza>) : RecyclerView.Adapter<PizzaAdapter.PizzaViewHolder>() { private lateinit var listener: PizzaAdapterListener inner class PizzaViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val textViewName: TextView = itemView.findViewById(R.id.textViewName) val textViewLocation: TextView = itemView.findViewById(R.id.textViewLocation) val ratingBar: RatingBar = itemView.findViewById(R.id.ratingBar) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PizzaViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.activity_current_pizza_palor_list, parent, false) return PizzaViewHolder(view) } override fun onBindViewHolder(holder: PizzaViewHolder, position: Int) { val pizza = pizzaList[position] holder.textViewName.text = pizza.name holder.textViewLocation.text = pizza.location holder.ratingBar.rating = pizza.rate?.toFloat() ?: 0f } override fun getItemCount(): Int { return pizzaList.size } fun setData(list: List<Pizza>) { pizzaList.clear() pizzaList.addAll(list) notifyDataSetChanged() } interface PizzaAdapterListener { fun onClick(position: Int) } fun getFilter(): Filter { return object : Filter() { override fun performFiltering(constraint: CharSequence?): FilterResults { val filteredList = mutableListOf<Pizza>() if (constraint == null || constraint.isEmpty()) { filteredList.addAll(pizzaList) } else { val filterPattern = constraint.toString().lowercase().trim() for (item in pizzaList) { if (item.name.lowercase().contains(filterPattern)) { filteredList.add(item) } } } val results = FilterResults() results.values = filteredList return results } override fun publishResults(constraint: CharSequence?, results: FilterResults?) { pizzaList = results?.values as MutableList<Pizza> notifyDataSetChanged() } } } fun setOnItemClickListener(_listener: PizzaAdapterListener) { listener = _listener } }
2. MainActivity关键错误修复
- 初始化并绑定适配器:之前未实例化
pizzaAdapter也未设置给RecyclerView,导致列表无数据源,同时SearchView无法联动。 - 移除局部变量覆盖:删除
val searchView = findViewById<SearchView>(R.id.searchView)中的val,使用全局变量。 - 联动适配器过滤逻辑:删除冗余的
filter方法,直接调用适配器的getFilter().filter()更新列表。
修复后的MainActivity:
class MainActivity : AppCompatActivity() { private lateinit var recyclerViewPizza: RecyclerView private lateinit var data: ArrayList<Pizza> private lateinit var pizzaAdapter: PizzaAdapter private lateinit var searchView: SearchView @SuppressLint("MissingInflatedId") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) recyclerViewPizza = findViewById(R.id.recyclerViewPizza) recyclerViewPizza.layoutManager = LinearLayoutManager(this) data = ArrayList() data.add(Pizza("Pizza Hut", "Deer Park", 3.1)) data.add(Pizza("Papa Johns", "Deer Park", 3.9)) data.add(Pizza("Richie's Pizza", "Commack", 4.4)) data.add(Pizza("Domino's Pizza", "Deer Park", 4.2)) // 初始化适配器并绑定到RecyclerView pizzaAdapter = PizzaAdapter(data.toMutableList()) recyclerViewPizza.adapter = pizzaAdapter searchView = findViewById(R.id.searchView) searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { pizzaAdapter.getFilter().filter(query) return true } override fun onQueryTextChange(newText: String?): Boolean { pizzaAdapter.getFilter().filter(newText) return true } }) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.toolmenu, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { return when (item.itemId) { R.id.add_item -> { startActivity(Intent(this@MainActivity, AddActivity::class.java)) true } else -> super.onOptionsItemSelected(item) } } }
3. 额外检查点
- 确认
activity_main.xml中存在R.id.searchView,如果SearchView在menu中,需在onCreateOptionsMenu中获取:override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.toolmenu, menu) val searchItem = menu?.findItem(R.id.action_search) val searchView = searchItem?.actionView as SearchView searchView.setOnQueryTextListener(...) return true } - 确保
Pizza数据类的字段定义正确,无空指针风险。
内容的提问来源于stack exchange,提问作者SRBeginnerDev
相关产品推荐
相关产品推荐

