【问题标题】:null cannot be cast to non-null type kotlin.collections.List - kotlinnull 不能转换为非 null 类型 kotlin.collections.List - kotlin
【发布时间】:2020-04-09 02:34:18
【问题描述】:

我正在尝试在 RecyclerView 中添加搜索 Filterable。但应用程序因以下错误而崩溃:

kotlin.TypeCastException: null 不能转换为非 null 类型 kotlin.collections.List 在 com.kabelash.movi​​es.ui.PostListAdapter$searchFilter$1.publishResults(PostListAdapter.kt:87) 在 android.widget.Filter$ResultsHandler.handleMessage(Filter.java:284) 在 android.os.Handler.dispatchMessage(Handler.java:107) 在 android.os.Looper.loop(Looper.java:214)

适配器:

class PostListAdapter: RecyclerView.Adapter<PostListAdapter.ViewHolder>(), Filterable {
    private lateinit var postListFiltered:List<Data>
    private lateinit var postListFull:List<Data>

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding: ListItemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.list_item, parent, false)
        return ViewHolder(binding)
    }

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

    override fun getItemCount(): Int {
        return if(::postListFiltered.isInitialized) postListFiltered.size else 0
    }

    fun updatePostList(postList:List<Data>){
        this.postListFiltered = postList
        notifyDataSetChanged()
    }

    class ViewHolder(private val binding: ListItemBinding): RecyclerView.ViewHolder(binding.root){
        private val viewModel = MoviesViewModel()

        fun bind(post:Data){
            viewModel.bind(post)
            binding.viewModel = viewModel
        }

    }

    override fun getFilter(): Filter? {
        return searchFilter
    }

    private val searchFilter: Filter = object : Filter() {
        override fun performFiltering(constraint: CharSequence?): FilterResults? {
            val filteredList: MutableList<Data> = ArrayList()
            if (constraint == null || constraint.isEmpty()) {
                filteredList.addAll(postListFull)
            } else {
                val filterPattern = constraint.toString().toLowerCase().trim()
                for (item in postListFull) {
                    if (item.title.toLowerCase().contains(filterPattern) || item.genre.toLowerCase().contains(filterPattern)) {
                        filteredList.add(item)
                    }
                }

            }
            val results = FilterResults()
            results.values = filteredList
            return results
        }

        override fun publishResults(constraint: CharSequence?,results: FilterResults) {
            postListFiltered = (results.values as List<Data>)
            notifyDataSetChanged()
        }
    }
}

如果您需要任何其他类文件,请告诉我。有人可以帮我解决吗?

【问题讨论】:

  • 看起来 result.values 在您的postListFiltered = (results.values as List&lt;Data&gt;) 中为空 - 这就是您崩溃的原因。 postListFiltered 不可为空。
  • 到目前为止,没有一个答案可以解释 results.values 为何可能为空。过滤器实现非常清楚地总是为其分配一个不可为空的值。您应该能够避免使用 postListFiltered = (results.values as List&lt;Data&gt;?).orEmpty() 立即出现错误,但这可能掩盖了您仍然需要解决的其他一些错误。
  • 您的日志是否包含带有标签“Filter”的警告和消息“PerformFiltering() 期间发生异常!” ?
  • @Tenfour04 postListFiltered = (results.values as List?).orEmpty() 实际上是一个答案!

标签: android kotlin android-recyclerview android-filterable


【解决方案1】:

就是这一行: results.values as List&lt;Data&gt;

results.values 为空,而你告诉它是一个非空列表,它不能这样做。

【讨论】:

    【解决方案2】:

    您必须在执行强制转换之前执行空检查,修改您的 pulishResults 方法如下。

       override fun publishResults(constraint: CharSequence?,results: FilterResults) {
                    postListFiltered = if(results == null || results.values == null)
                                           ArrayList<Data>() 
                                       else
                                            results.values
                    notifyDataSetChanged()
                }
    

    【讨论】:

      【解决方案3】:

      正如其他两个答案正确指出的那样,您的 results.values 为空。但是代码清楚地表明,从performFiltering 返回的FilterResults 总是有一个非空的values 字段。怎么会这样?

      简要查看Filter 源代码给出了一个可能的答案:

      // Filter.RequestHandler.handleMessage(Message msg)
      
      try {
          args.results = performFiltering(args.constraint);
      } catch (Exception e) {
          args.results = new FilterResults();
          Log.w(LOG_TAG, "An exception occured during performFiltering()!", e);
      }
      

      简单来说,如果performFiltering() 抛出异常,过滤器会捕获异常并使用空的FilterResults 来代替原本会返回的内容。此异常的堆栈跟踪可以在 logcat 中找到。

      查看您的performFiltering 函数,唯一突出的例外是UninitializedPropertyAccessException。如果这是抛出的异常,您可以通过检查 fullPostList 属性是否已初始化或将其显式初始化为空列表来修复它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多