【问题标题】:NullPointerException: Attempt to invoke interface method 'boolean java.util.Collection.isEmpty()' on a null object referenceNullPointerException:尝试在空对象引用上调用接口方法“boolean java.util.Collection.isEmpty()”
【发布时间】:2021-08-11 01:33:06
【问题描述】:

我正在尝试从 API 获取一些数据,并且由于我有这个回调指向一个空响应,所以我收到以下错误:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.newsapp.develop, PID: 19479
    java.lang.NullPointerException: Attempt to invoke interface method 'boolean java.util.Collection.isEmpty()' on a null object reference
        at com.example.newsapp.API.NewsRemoteDataSource$getNewsList$1.onResponse(NewsRemoteDataSource.kt:21)
        at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
        at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$hVGjmafRi6VitDIrPNdoFizVAdk.run(Unknown Source:6)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7094)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)

如何在保留功能的同时修复它?这意味着,保持回调并获得 OnSuccess 的结果。

这是带有回调的适配器:

package com.example.newsapp.Adapters

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.newsapp.ArticlesData
import com.example.newsapp.R
import com.example.newsapp.databinding.NewsItemBinding
import com.squareup.picasso.Picasso

class RecyclerAdapter (private var Articles: List<ArticlesData>) : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>(){

    inner class ViewHolder(
        view: View
    ): RecyclerView.ViewHolder(view){
        private val binding = NewsItemBinding.bind(view)

        val itemTitle: TextView = binding.tvTitle
        val itemImage: ImageView = binding.ivNewsImage

        fun bind(articles: ArticlesData){
            Picasso.get().load(articles.urlToImage).into(binding.ivNewsImage)
            itemTitle.text = articles.Title
        }
    }

    interface Callback {
        fun onArticleClicked(articleClicked: ArticlesData)
    }

    var callback: Callback? = null

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

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

        holder.itemImage.setOnClickListener {
            callback?.onArticleClicked(Articles[position])
        }

    }

    override fun getItemCount(): Int {
        return Articles.size
    }

    fun setNewsList(newList: List<ArticlesData>) {
        this.Articles = newList
        notifyDataSetChanged()
    }


}

这是问题所在的远程数据源:

package com.example.newsapp.API

import com.example.newsapp.ArticlesData
import com.example.newsapp.NewsListResponse
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

class NewsRemoteDataSource {
    fun getNewsList(networkResponse: NetworkResponse<List<ArticlesData>>) {
        val service = RetrofitServices.instance
            .create(APIService::class.java)
            .getNewsList()

        service.enqueue(object : Callback<NewsListResponse> {
            override fun onResponse(
                call: Call<NewsListResponse>,
                response: Response<NewsListResponse>
            ) {
                val resource = response.body()?.run {
                    if (results.isNotEmpty())
                        Resource(NetworkStatus.SUCCESS, results)
                    else
                        Resource(NetworkStatus.ERROR)
                } ?: run {
                    Resource(NetworkStatus.ERROR)
                }
                networkResponse.onResponse(resource)
            }

            override fun onFailure(call: Call<NewsListResponse>, t: Throwable) {
                networkResponse.onResponse(Resource(NetworkStatus.ERROR, message = t.message))
            }
        })
    }


}

interface NetworkResponse<T> {
    fun onResponse(value: Resource<T>)
}

API 响应:

data class NewsResponse (
    @SerializedName("status") var Status: String,
    @SerializedName("totalResults") var totalResults: Int,
    @SerializedName("articles") var Articles: List<ArticlesData>
    )

@Parcelize
data class ArticlesData (
    @SerializedName("source") var Source: @RawValue SourceData,
    @SerializedName("author") var Author: String? = " ",
    @SerializedName("title") var Title: String,
    @SerializedName("description") var Description: String,
    @SerializedName("url") var Url: String,
    @SerializedName("urlToImage") var urlToImage: String? =" ",
    @SerializedName("publishedAt") var publishedAt: String,
    @SerializedName("content") var Content: String? = " "
) : Parcelable

data class SourceData (
    @SerializedName("name") var Name: String,
)

data class NewsListResponse(
    val results: List<ArticlesData>
)

【问题讨论】:

  • 我没有看到任何地方 results 实际上被设置为任何东西
  • 由于您使用的是响应,您可以查看响应代码:stackoverflow.com/questions/31808083/…
  • @tyczj 我添加了有关 api 响应的信息
  • @DanielNugent 我可以在调试响应中看到结果不为空:I/okhttp.OkHttpClient:

标签: android kotlin


【解决方案1】:

set results?.isNotEmpty() == true 这会导致异常,因为结果可能为空

【讨论】:

  • 恐怕即使我这样做了,错误仍然会发生
【解决方案2】:

由于某种原因result 似乎是null,您需要将您的 if 条件修改为

if (results.isNullOrEmpty())
    Resource(NetworkStatus.ERROR)
else
    Resource(NetworkStatus.SUCCESS, results)

【讨论】:

  • 如果我这样做,它只会出错,但我已经让这段代码工作了,然后我才能在日志中看到结果不为空
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 2018-02-05
  • 1970-01-01
  • 2015-03-09
  • 2019-12-20
  • 2018-07-24
相关资源
最近更新 更多