NullPointerException与适配器



我有这个观察者为我的视图模型,所以我可以设置我的适配器,但是,当我运行应用程序时,它给了我这一行的NullPointerException错误:

japaneseAdapter = it.data?.let { it1 -> JapaneseAdapter(it1) }!!

这是一行的活动:

@AndroidEntryPoint
class JapaneseActivity : AppCompatActivity() {
private lateinit var binding: ActivityJapaneseBinding
private val japaneseViewModel by viewModels<JapaneseViewModel>()
private lateinit var japaneseAdapter: JapaneseAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityJapaneseBinding.inflate(layoutInflater)
setContentView(binding.root)
japaneseViewModel.japaneseResponse.observe(this, {
when(it.status){
Resource.Status.LOADING -> { }
Resource.Status.SUCCESS -> {
japaneseAdapter = it.data?.let { it1 -> JapaneseAdapter(it1) }!!
binding.rvNews.adapter = japaneseAdapter
}
Resource.Status.ERROR -> { Log.d("ERROR","ERROR RAISED") }
}
})
}
}

这是适配器:

class JapaneseAdapter(private var japaneseResponse: List<JapaneseResponse>) :
RecyclerView.Adapter<JapaneseAdapter.ViewHolder>() {
inner class ViewHolder(
view: View
) : RecyclerView.ViewHolder(view) {
private val binding = NewsItemsBinding.bind(view)
private val itemTitle: TextView = binding.tvTitle
private val itemImage: ImageView = binding.ivNews
private val itemDescription: TextView = binding.tvDescription
fun bind(response: JapaneseResponse) {
Picasso.get().load(response.urlToImage).into(itemImage)
itemTitle.text = response.Title
itemDescription.text = response.Description
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.news_items, parent, false)
return ViewHolder(v)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(japaneseResponse[position])
}
override fun getItemCount(): Int {
return japaneseResponse.size
}
}

通用数据源:

abstract class BaseDataSource {
protected suspend fun <T> getResult(call: suspend () -> Response<ApiResponse<T>>): Resource<T> {
try {
val response = call()
//            if(response.isSuccessful) {
//                val body = response.body()?.data
//                if(body != null) return Resource.success(body)
//            }
val body = response.body()?.data
return Resource.success(body)
//return Resource.error("${response.code()}: ${response.message()}")
} catch (e: Exception) {
return Resource.error(e.message ?: "Generic error")
}
}
}
data class Resource<out T>(val status: Status, val data: T?, val message: String?) : Serializable {
enum class Status {
SUCCESS,
ERROR,
LOADING
}
companion object {
fun <T> success(data: T?): Resource<T> {
return Resource(
Status.SUCCESS,
data,
null
)
}
fun <T> error(message: String, data: T? = null): Resource<T> {
return Resource(
Status.ERROR,
data,
message
)
}
fun <T> loading(data: T? = null): Resource<T> {
return Resource(
Status.LOADING,
data,
null
)
}
}
fun isSuccessful() = status == Status.SUCCESS
fun isError() = status == Status.ERROR
fun isLoading() = status == Status.LOADING
}

日本新闻的数据来源:

class JapaneseDataSource @Inject constructor(private val japaneseService: JapaneseService) :
BaseDataSource() {
suspend fun getJpNews() = getResult { japaneseService.jpNews() }
}

存储库:

class JapaneseRepository @Inject constructor(
private val remote: JapaneseDataSource
) {
suspend fun jpNews() =
remote.getJpNews()
}
服务:

interface JapaneseService {
@GET("/v2/top-headlines?country=jp&apiKey=77acc490875643c5b2328fb615e0cf83")
suspend fun jpNews(): Response<ApiResponse<List<JapaneseResponse>>>
}

我可以看到响应是存在的,因为我有okhttp为我记录它,但出于某种原因,它似乎是空的,我不知道为什么…任何帮助吗?

japaneseAdapter = it.data?.let { it1 -> JapaneseAdapter(it1) }!!

!!是Kotlin的"崩溃应用程序";操作符。它说,如果您将!!应用于null的值,则希望使应用程序崩溃。作为Kotlin程序员,您的目标是避免使用!!

在这种情况下,您在那一行崩溃并出现错误的事实意味着!!正在应用于null。如果it.data求值为null,则会发生。

it.data显示为Resource对象,statusSUCCESS。因此,假定您正在调用success(),其值为null

考虑到所有这些,你需要使用你的调试器,看看为什么val body = response.body()?.data被评估为null,或者看看你在哪里得到Resourcenull数据。

并且,请尽量避免使用!!