如何通过SearchView过滤自定义Book对象并刷新RecyclerView?
解决方案:用SearchView过滤自定义Book对象列表
第一步:改造RecyclerAdapter,支持过滤
咱们得给你的RecyclerAdapter加上过滤能力,核心思路是维护一份原始的完整书籍列表,每次搜索都从这份原始列表里筛选匹配的Book对象,再更新RecyclerView的显示列表——这样就不会因为多次过滤导致数据丢失啦。
修改后的完整Adapter代码如下:
class BookAdapter(private var bookList: MutableList<Book>) : RecyclerView.Adapter<BookAdapter.BookHolder>(), Filterable { // 保存原始的完整书籍列表,避免多次过滤后数据丢失 private val fullBookList = ArrayList(bookList) inner class BookHolder(itemView: View) : RecyclerView.ViewHolder(itemView) override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BookHolder { val inflater = LayoutInflater.from(parent.context) val view = inflater.inflate(R.layout.recyler_row, parent, false) return BookHolder(view) } override fun onBindViewHolder(holder: BookHolder, position: Int) { val currentBook = bookList[position] holder.itemView.isim.text = currentBook.kitapismi holder.itemView.aciklama.text = currentBook.kitapaciklama holder.itemView.recyler_email.text = currentBook.kullaniciemail Picasso.get().load(currentBook.gorselurl).into(holder.itemView.recyler_image) holder.itemView.setOnClickListener{ val intent = Intent(holder.itemView.context, BookDetails::class.java) intent.putExtra("bookIsmi", currentBook.kitapismi) intent.putExtra("bookAciklama", currentBook.kitapaciklama) intent.putExtra("bookImage", currentBook.gorselurl) intent.putExtra("email", currentBook.kullaniciemail) holder.itemView.context.startActivity(intent) } } override fun getItemCount(): Int { return bookList.size } // 实现Filterable接口,核心过滤逻辑在这里 override fun getFilter(): Filter { return object : Filter() { // 后台线程执行过滤,避免阻塞UI override fun performFiltering(constraint: CharSequence?): FilterResults { val filteredList = mutableListOf<Book>() val query = constraint?.toString()?.lowercase(Locale.getDefault()) ?: "" if (query.isEmpty()) { // 搜索框为空时,显示全部书籍 filteredList.addAll(fullBookList) } else { // 遍历原始列表,匹配书籍名称/描述(你可以自定义匹配字段) for (book in fullBookList) { val bookName = book.kitapismi?.lowercase(Locale.getDefault()) ?: "" val bookDesc = book.kitapaciklama?.lowercase(Locale.getDefault()) ?: "" // 匹配名称或描述,满足任一条件就加入过滤列表 if (bookName.contains(query) || bookDesc.contains(query)) { filteredList.add(book) } } } val results = FilterResults() results.values = filteredList return results } // 更新UI线程的列表,并刷新RecyclerView override fun publishResults(constraint: CharSequence?, results: FilterResults?) { bookList.clear() bookList.addAll(results?.values as MutableList<Book>) notifyDataSetChanged() } } } }
第二步:在BooksActivity中绑定SearchView和过滤逻辑
接下来在你的BooksActivity里,给SearchView设置文本监听,把用户输入的内容传给Adapter的过滤方法:
class BooksActivity : AppCompatActivity() { private lateinit var recyclerView: RecyclerView private lateinit var bookAdapter: BookAdapter // 这里替换成你实际获取书籍列表的逻辑(比如从数据库/网络加载) private val bookList = mutableListOf<Book>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_books) recyclerView = findViewById(R.id.recyclerView) recyclerView.layoutManager = LinearLayoutManager(this) // 初始化Adapter bookAdapter = BookAdapter(bookList) recyclerView.adapter = bookAdapter // 绑定SearchView的监听 val searchView = findViewById<SearchView>(R.id.search_book) searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { // 点击搜索按钮时触发过滤 bookAdapter.filter.filter(query) return true } override fun onQueryTextChange(newText: String?): Boolean { // 输入文本实时变化时触发过滤 bookAdapter.filter.filter(newText) return true } }) } }
关键细节说明
- 自定义匹配字段:在
performFiltering方法里,我设置的是匹配书籍名称(kitapismi)和描述(kitapaciklama),你可以根据需求调整,比如只匹配名称,或者加上用户邮箱(kullaniciemail)。 - 大小写不敏感:把搜索关键词和书籍字段都转成小写,这样搜索时不会区分大小写,提升用户体验。
- 原始列表的必要性:一定要维护
fullBookList,如果直接在显示列表上过滤,多次搜索后会导致数据丢失,因为每次过滤都要基于原始的完整数据。
内容的提问来源于stack exchange,提问作者mythredd
相关产品推荐
相关产品推荐

