我有这个观察者为我的视图模型,所以我可以设置我的适配器,但是,当我运行应用程序时,它给了我这一行的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
对象,status
为SUCCESS
。因此,假定您正在调用success()
,其值为null
。
考虑到所有这些,你需要使用你的调试器,看看为什么val body = response.body()?.data
被评估为null
,或者看看你在哪里得到Resource
与null
数据。
并且,请尽量避免使用!!
。