'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 |
|---|
