Android 搜索视图引发异常(空对象引用)

Android 搜索视图引发异常(空对象引用),android,android-recyclerview,android-viewpager,searchview,android-pageradapter,Android,Android Recyclerview,Android Viewpager,Searchview,Android Pageradapter,我有一个片段,它使用FragmentPagerAdapter并加载另外两个带有两个回收器视图的片段。我正试图根据在searchView中键入的文本筛选recycler视图中的项目。我并没有使用单独的搜索活动,相反,我尝试对两个回收者视图使用一个过滤器 我为搜索功能编写了以下代码(我为这两个片段实现了相同的逻辑,即ListOneFragment和ListTwoFragment,它们都有各自的recycleView) 片段: class ListOneFragment : Fragment() {

我有一个片段,它使用FragmentPagerAdapter并加载另外两个带有两个回收器视图的片段。我正试图根据在searchView中键入的文本筛选recycler视图中的项目。我并没有使用单独的搜索活动,相反,我尝试对两个回收者视图使用一个过滤器

我为搜索功能编写了以下代码(我为这两个片段实现了相同的逻辑,即ListOneFragment和ListTwoFragment,它们都有各自的recycleView)

片段:

class ListOneFragment : Fragment() {
      lateinit var adapter: ListOneRecyclerViewAdapter
      lateinit var listonerv: RecyclerView

      viewModel.getListOne().observe(viewLifecycleOwner,Observer {
                recyclerView.apply {
                    layoutManager = LinearLayoutManager(context,RecyclerView.VERTICAL, false)
                    adapter = ListOneRecyclerViewAdapter(it, mViewModel)
                }
                adapter = recyclerView.adapter as ListOneRecyclerViewAdapter
            })
            listonerv = findViewById(R.id.recyclerView)

     listone_search.setOnQueryTextListener(object : SearchView.OnQueryTextListener { 
//------------------------The exception is being thrown for the line above------------------------
                override fun onQueryTextSubmit(query: String?): Boolean {
                    return false
                }
                override fun onQueryTextChange(newText: String?): Boolean {
                    adapter.filter.filter(newText)
                    return false
                }
            })
class ListOneRecyclerViewAdapter(
    private val firstList : ArrayList<ListOne>,
    private val viewModel: ListViewModel
): RecyclerView.Adapter<ListOneViewHolder>(), Filterable {

var filterList = ArrayList<ListOne>()

init{
    filterList = firstList //so that when the search bar is empty, all items are populated
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
        ListOneViewHolder(viewModel,
            LayoutInflater.from(parent.context).inflate(R.layout.item_one, parent, false))

override fun getItemCount() = filterList.size

override fun onBindViewHolder(holder: ListOneViewHolder, position: Int) {
        holder.bind(filterList[position])
    }

override fun getFilter(): Filter {
        Log.d("Test", "Inside getFilter")
        return object : Filter() {
            override fun performFiltering(constraint: CharSequence?): FilterResults {
                val charSearch = constraint.toString()
                if (charSearch.isEmpty()) {
                    Log.d("Test","char is empty")
                    filterList = firstList
                } else {
                    Log.d("Test","something typed")
                    val resultList = ArrayList<ListOne>()
                    for (row in firstList) {
                        if (row.name.toLowerCase(Locale.ROOT).contains(charSearch.toLowerCase(Locale.ROOT))) {
                            resultList.add(row)
                        }
                    }

                    filterList = resultList

                    Log.d("Test",filterList.toString())
                }
                val filterResults = FilterResults()
                filterResults.values = filterList
                Log.d("Filter",filterResults.values.toString())
                return filterResults
            }


            @Suppress("UNCHECKED_CAST")
            override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
                filterList = results?.values as ArrayList<ListOne>
                Log.d("Publish",filterList.toString())
                notifyDataSetChanged()
            }
        }
    }
回收服务适配器:

class ListOneFragment : Fragment() {
      lateinit var adapter: ListOneRecyclerViewAdapter
      lateinit var listonerv: RecyclerView

      viewModel.getListOne().observe(viewLifecycleOwner,Observer {
                recyclerView.apply {
                    layoutManager = LinearLayoutManager(context,RecyclerView.VERTICAL, false)
                    adapter = ListOneRecyclerViewAdapter(it, mViewModel)
                }
                adapter = recyclerView.adapter as ListOneRecyclerViewAdapter
            })
            listonerv = findViewById(R.id.recyclerView)

     listone_search.setOnQueryTextListener(object : SearchView.OnQueryTextListener { 
//------------------------The exception is being thrown for the line above------------------------
                override fun onQueryTextSubmit(query: String?): Boolean {
                    return false
                }
                override fun onQueryTextChange(newText: String?): Boolean {
                    adapter.filter.filter(newText)
                    return false
                }
            })
class ListOneRecyclerViewAdapter(
    private val firstList : ArrayList<ListOne>,
    private val viewModel: ListViewModel
): RecyclerView.Adapter<ListOneViewHolder>(), Filterable {

var filterList = ArrayList<ListOne>()

init{
    filterList = firstList //so that when the search bar is empty, all items are populated
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
        ListOneViewHolder(viewModel,
            LayoutInflater.from(parent.context).inflate(R.layout.item_one, parent, false))

override fun getItemCount() = filterList.size

override fun onBindViewHolder(holder: ListOneViewHolder, position: Int) {
        holder.bind(filterList[position])
    }

override fun getFilter(): Filter {
        Log.d("Test", "Inside getFilter")
        return object : Filter() {
            override fun performFiltering(constraint: CharSequence?): FilterResults {
                val charSearch = constraint.toString()
                if (charSearch.isEmpty()) {
                    Log.d("Test","char is empty")
                    filterList = firstList
                } else {
                    Log.d("Test","something typed")
                    val resultList = ArrayList<ListOne>()
                    for (row in firstList) {
                        if (row.name.toLowerCase(Locale.ROOT).contains(charSearch.toLowerCase(Locale.ROOT))) {
                            resultList.add(row)
                        }
                    }

                    filterList = resultList

                    Log.d("Test",filterList.toString())
                }
                val filterResults = FilterResults()
                filterResults.values = filterList
                Log.d("Filter",filterResults.values.toString())
                return filterResults
            }


            @Suppress("UNCHECKED_CAST")
            override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
                filterList = results?.values as ArrayList<ListOne>
                Log.d("Publish",filterList.toString())
                notifyDataSetChanged()
            }
        }
    }

我正在尝试使用searchView,而不只是为了搜索而引入其他活动。这一个非常适用于具有一个回收器视图的单个片段。下面是一个例子()

我将尝试回答,希望我能提供帮助


我不清楚,但我猜显示的片段代码是您在viewpager中显示的片段代码之一,对吗?如果我在这里是正确的,您的searchview不在您的ListOneFragment中,这就是为什么您会得到一个空异常,因为search_视图不在其布局中。要解决这个问题,其中一种方法是在ListOneFragment和ListTwoFragment中使用appbar/searchview。

Yes。我在ListOne和ListTwo片段中没有它。我有一个用于片段的通用应用程序栏,它使用视图寻呼机加载其他2个帧。所以我需要包含2个搜索视图?我只想保留一个,但我会尝试一下。你可以用很多方法来做到。您可以在commom片段中调用search_视图,该视图会使您的viewpager膨胀。但是我有两个recycler视图适配器,我正在使用它们将值传递给过滤器。所以我在公共片段中使用它,我不知道如何为这两个视图维护一个适配器。我不理解你的上一条评论。你能详细解释一下吗?!需要回收器视图适配器的内容才能将其传递到筛选器。所以我这里有两个回收器视图,如果我在公共片段中使用searchView,我不知道需要从哪个回收器视图中进行过滤。有没有一种方法可以从寻呼机适配器获取数据,这样我就可以动态地看到用户在哪个选项卡上,并相应地过滤结果。但就目前而言,正如您所提到的,两个单独片段的搜索视图目前运行良好。