null 不能转换为非 null 类型 kotlin.collections.List - kotlin

Posted

技术标签:

【中文标题】null 不能转换为非 null 类型 kotlin.collections.List - kotlin【英文标题】:null cannot be cast to non-null type 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 不可为空。 这能回答你的问题吗? What is a NullPointerException, and how do I fix it? 到目前为止,没有一个答案可以解释 results.values 为何可能为空。过滤器实现非常清楚地总是为其分配一个不可为空的值。您应该能够避免使用 postListFiltered = (results.values as List&lt;Data&gt;?).orEmpty() 立即出现错误,但这可能掩盖了您仍然需要解决的其他一些错误。 您的日志是否包含带有标签“Filter”的警告和消息“PerformFiltering() 期间发生异常!” ? @Tenfour04 postListFiltered = (results.values as List?).orEmpty() 实际上是一个答案! 【参考方案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 属性是否已初始化或将其显式初始化为空列表来修复它。

【讨论】:

以上是关于null 不能转换为非 null 类型 kotlin.collections.List - kotlin的主要内容,如果未能解决你的问题,请参考以下文章

kotlin.TypeCastException: null 不能转换为非 null 类型 com.midsizemango.databasekotlin.Note

致命异常 java.lang.NullPointerException: null 不能转换为非 null 类型 kotlin.String

null 不能转换为非 null 类型 android.support.v4.view.ViewPager - KOTLIN

Android Kotlin:null 不能转换为非 null 类型 com.android.app.ui.category.CategoryAdapter.ViewHolder 想要在 recycl

Nest JS GraphQL“不能为非空返回null” [重复]

使用 Linq 的 Where/Select 过滤掉 null 并将类型转换为不可为 null 不能做成扩展方法