【问题标题】:Search View throwing exception (Null Object Reference)搜索视图抛出异常(空对象引用)
【发布时间】:2020-07-09 18:23:42
【问题描述】:

我有一个使用 FragmentPagerAdapter 的片段,并使用两个回收器视图加载 2 个其他片段。我正在尝试根据在 searchView 中键入的文本过滤回收站视图的项目。我没有使用单独的搜索活动,而是尝试对两个回收者视图使用过滤器。

我有以下用于搜索功能的代码(我正在为两个片段实现相同的逻辑,即 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
                }
            })

RecyclerViewAdapter:

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()
            }
        }
    }

XML:(在 App Bar 中具有视图 Pager 和搜索视图的通用片段)

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".screens.first.ListOneFragment">
<include
    layout="@layout/layout_background_image" />

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:layout_scrollFlags="scroll|enterAlways"
        app:navigationIcon="?homeAsUpIndicator"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        />


    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:tabIndicatorColor="@color/white"
        app:tabIndicatorHeight="@dimen/_2sdp"
        app:tabSelectedTextColor="@color/white" />

    <androidx.appcompat.widget.SearchView
        android:id="@+id/listone_search"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textCursorDrawable="@null"
        app:queryHint="@string/Search"
        android:elevation="@dimen/_8sdp"
        app:iconifiedByDefault="false"
        app:queryBackground="@null"
        app:layout_constraintTop_toBottomOf="@+id/appbar"
        app:layout_constraintStart_toStartOf="parent"/>

</com.google.android.material.appbar.AppBarLayout>

<androidx.viewpager.widget.ViewPager
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

但我得到以下异常:

java.lang.NullPointerException: Attempt to invoke virtual method 'void androidx.appcompat.widget.SearchView.setOnQueryTextListener(androidx.appcompat.widget.SearchView$OnQueryTextListener)' on a null object reference

我正在尝试使用 searchView 而不为搜索引入其他活动。这对于具有一个回收器视图的单个片段非常有效。这是一个例子 (https://johncodeos.com/how-to-add-search-in-recyclerview-using-kotlin/)

【问题讨论】:

    标签: android android-recyclerview android-viewpager searchview android-pageradapter


    【解决方案1】:

    我会尽量回答,希望能帮到你。

    我不清楚,但我猜显示的片段代码是您在查看器中显示的片段代码之一,对吧?如果我在这里是正确的,那么您的 searchview 不在您的 ListOneFragment 中,这就是为什么给您一个空异常的原因,因为 search_view 不在其布局中。要解决这个问题,其中一种方法是将 appbar/searchview 放在 ListOneFragmentListTwoFragment 中。

    【讨论】:

    • 是的。我在 ListOne 和 ListTwo 片段中没有它。我有一个通用的应用栏,用于使用 View Pager 加载其他 2 个框架的片段。所以我需要包括 2 个搜索视图?我想只保留一个,但我会试一试。
    • 您可以通过多种方式做到这一点。您可以在您的 commom 片段中调用 search_view,它会膨胀您的 viewpager。
    • 但我有 2 个回收器视图适配器,用于将值传递给过滤器。所以我在公共片段中使用它,我不知道如何为两个视图维护一个适配器。
    • 我不明白你的最后评论。能详细解释一下吗?!
    • 需要回收器视图适配器的内容才能将其传递给过滤器。所以我在这里有 2 个回收器视图,如果我在公共片段中使用 searchView,我不知道我需要从哪个回收器视图中过滤。有没有办法从寻呼机适配器获取数据,以便我可以动态查看用户在哪个选项卡上并相应地过滤结果。但就目前而言,正如您所提到的,两个单独片段的搜索视图现在都可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-29
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 1970-01-01
    相关资源
    最近更新 更多