I'm trying to get some data from an API and since I have this callback pointed to a null response, I get the following error:
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)
How can I fix it while still keeping the functionality? That means, keeping the callback and also getting the results OnSuccess.
This is the adapter with the callback:
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()
}
}
This is the remote data source where the issue comes from:
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 response:
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>
)