'Kotlin Retrofit response.data() returned null with kotlin

I'm trying to fetch an API in recyclerview in my breakingNewsFragment but it still a white screen

i use navigation between fragments from:

class NewsActivity : AppCompatActivity() {

lateinit var newsViewModel: NewsViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    var newsRepository = NewsRepository(ArticleDataBase(this))
    var newsViewModelFactoryProvider = NewsViewModelFactory(newsRepository)
    newsViewModel = ViewModelProvider(this,newsViewModelFactoryProvider).get(NewsViewModel::class.java)

    setContentView(R.layout.activity_news)

    bottomNavigationView.setupWithNavController(navHostFragmentNews.findNavController())


} }

other fragments work with api but this fragment which i hosted in navigation and xml not work

breakingNewsFramgnet:

/////////////i think here is problem////////////////

class BreakingNewsFragment : Fragment(R.layout.fragment_breaking_news) {

lateinit var newsViewModel : NewsViewModel
lateinit var articleRecyclerAdapter: ArticleRecyclerAdapter

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    newsViewModel = (activity as NewsActivity).newsViewModel
    setupRecyclerView()

    articleRecyclerAdapter.setOnItemClickListener {
        var bundle= Bundle().apply {
            putSerializable("article",it)
        }
        findNavController().navigate(R.id.action_breakingNewsFragment_to_articleFragment, bundle)
    }

    newsViewModel.breakingNews.observe(viewLifecycleOwner, Observer { response ->

        when(response){
            is Resource.Success -> {
                hideProgressBar()
                response.data?.let { newsResponse -> { ///////////////i think here is problem//////////////
                    Toast.makeText(activity,"success",Toast.LENGTH_SHORT).show()
                    articleRecyclerAdapter.differ.submitList(newsResponse.articles)
                } }
            }
            is Resource.Failed ->{
                hideProgressBar()
                response.message?.let {message ->{

                    Toast.makeText(activity,"the error $message",Toast.LENGTH_SHORT).show()
                } }
            }
            is Resource.Loading ->{
                showProgressBar()
            }
        }
    })
}

fun setupRecyclerView(){
    articleRecyclerAdapter= ArticleRecyclerAdapter()
    rvBreakingNews.adapter= articleRecyclerAdapter
}

fun hideProgressBar() {
    paginationProgressBar.visibility = View.INVISIBLE
}

fun showProgressBar() {
    paginationProgressBar.visibility = View.VISIBLE
}}

my newsViewModel:

class NewsViewModel(private var newsRepository: NewsRepository) : ViewModel() {

var breakingNews : MutableLiveData<Resource<NewsResponse>> = MutableLiveData()
var breakingNewsPage =1
//to put every page in one list
var breakingNewsResponse :NewsResponse ?=null

var searchingNews : MutableLiveData<Resource<NewsResponse>> = MutableLiveData()
var SearchingNewsPage=1
var searchingNewsResponse :NewsResponse ?=null

init {
    getBreakingNews("us")
}

//region get from view model

fun getBreakingNews(countryCode: String) = viewModelScope.launch {

    //because will waite to get data
    breakingNews.postValue(Resource.Loading())
    val response = newsRepository.getBreakingNews(countryCode,breakingNewsPage)
    //after get data maybe success or failed to get
    breakingNews.postValue(handelBreakingNewsResponse(response))
}

fun searchingNews(searchQuery:String)= viewModelScope.launch {

    searchingNews.postValue(Resource.Loading())
    val response = newsRepository.getSearchingNews(searchQuery,SearchingNewsPage)
    searchingNews.postValue(handelSearchingNewsResponse(response))
}

//endregion

fun handelBreakingNewsResponse(response: Response<NewsResponse>): Resource<NewsResponse> {
    //success to get data
    if (response.isSuccessful){
        // lambda refer to alternative of (it) to make it more clear
        response.body()?.let { resultResponse ->
            return Resource.Success(resultResponse)
        }

    }
    return Resource.Failed(response.message())
}

fun handelSearchingNewsResponse(response: Response<NewsResponse>) : Resource<NewsResponse> {

    if(response.isSuccessful){
        response.body()?.let { newsResponse ->
        return Resource.Success(newsResponse)
        }
    }
    return Resource.Failed(response.message())
}

where resource class is a set parameter and gets

newsRepoistory:

class NewsRepository(private var articleDataBase: ArticleDataBase) {

suspend fun getBreakingNews(countryCode : String ,pageNumber : Int) =
    NewsRetrofit.api.getBreakingNews(countryCode,pageNumber)

suspend fun getSearchingNews(searchQuery:String,pageNumber:Int) =
    NewsRetrofit.api.getSearchingNews(searchQuery,pageNumber)}

and retrofit:

class NewsRetrofit {

companion object {

    val retrofit by lazy {

        val loggingInterceptor = HttpLoggingInterceptor()
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)

        val client = OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .build()

        Retrofit.Builder().baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build()
    }

    val api by lazy {

        retrofit.create(NewsApi::class.java)
    }
}}

and the newsApi which take from json:

interface NewsApi {

@GET("v2/top-headlines")
suspend fun getBreakingNews(
    @Query("country")
    countryCode:String = "us",
    @Query("page")
    pageNumber:Int=1 ,
    @Query("apiKey")
    apiKey:String=API_KEY,
) : Response<NewsResponse>}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source