Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

I can't show my data from the API? Kotlin Android

First one it’s my repo : https://github.com/Berkayszk/FiWoApp

I am getting my data using retrofit and using paging adapter. When I want to show my data using my recyclerView in my MovieFragment, I see that no data is coming. What is the reason for this error? I’ve been dealing with this problem for 3 days and I couldn’t find a solution.

Movie Fragment = Showing my movies.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

@AndroidEntryPoint
class MovieFragment : Fragment(R.layout.fragment_movie) {

private var _binding: FragmentMovieBinding? = null
private val binding get() = _binding!!
private val viewModel: MovieViewModel by viewModels()
private lateinit var movieAdapter: PopularMovieAdapter
override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View {
    // Inflate the layout for this fragment
    _binding = FragmentMovieBinding.inflate(layoutInflater, container, false)
    return binding.root
}

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


    loadingData()
    setUpRv()
}


private fun loadingData() {

        movieAdapter = PopularMovieAdapter()
        lifecycleScope.launch {
            viewModel.moviesList.collect { pagingData ->
                movieAdapter.submitData(pagingData)

            }
        }
}
private fun setUpRv(){
    movieAdapter = PopularMovieAdapter()
    binding.recyclerView.apply {

        layoutManager = StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)
        adapter = movieAdapter
        setHasFixedSize(true)
    }

}
override fun onDestroy() {
    super.onDestroy()
    _binding = null
}

}

PopularMovieAdapter = Paging Adapter

 class PopularMovieAdapter :  PagingDataAdapter<com.example.fiwoapp.model.popularmovie.Result,PopularMovieAdapter.PopularMovieHo lder>(
diffCallBack) {
class PopularMovieHolder(val binding : PopularMovieRowBinding) : ViewHolder(binding.root)

companion object {
 val diffCallBack = object : DiffUtil.ItemCallback<com.example.fiwoapp.model.popularmovie.Result>(){
    override fun areItemsTheSame(oldItem: com.example.fiwoapp.model.popularmovie.Result, newItem: com.example.fiwoapp.model.popularmovie.Result): Boolean {
        return oldItem.id==newItem.id
    }

    override fun areContentsTheSame(oldItem: com.example.fiwoapp.model.popularmovie.Result, newItem: com.example.fiwoapp.model.popularmovie.Result): Boolean {
        return oldItem == newItem
    }
}
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PopularMovieHolder {
    return PopularMovieHolder(PopularMovieRowBinding.inflate(LayoutInflater.from(parent.context),parent,false))
}

override fun onBindViewHolder(holder: PopularMovieHolder, position: Int) {
    val currentItem = getItem(position)
    holder.binding.apply {
        movieName.text = currentItem!!.title
        val imageLink = "${Constants.IMAGE_BASE_UR}+${currentItem.poster_path}"
        imageView.load(imageLink){
            crossfade(true)
            crossfade(100)

        }
    }
}

Paging Source

class PopularMovieSource(private val repository: MovieShowRepository) :PagingSource<Int,Result>(){

override suspend fun load(params: LoadParams<Int>): LoadResult<Int,Result> {
    return try {
        val currentPage = params.key ?: 1
        val response = repository.getPopularMovie(currentPage)
        val data = response.body()!!.results
        val responseData = mutableListOf<Result>()
        responseData.addAll(data)

        LoadResult.Page(
            data = responseData,
            prevKey = if (currentPage == 1) null else -1,
            nextKey = currentPage.plus(1)
        )
    } catch (e: Exception) {
        LoadResult.Error(e)
    } catch (exception: HttpException) {
        LoadResult.Error(exception)
    }

}

override fun getRefreshKey(state: PagingState<Int, com.example.fiwoapp.model.popularmovie.Result>): Int? {
    return null
}

My ViewModel

@HiltViewModel class MovieViewModel @Inject constructor(
private val repository: MovieShowRepository,
private val apiService: ApiService

) : ViewModel() {

val loading = MutableLiveData<Boolean>()

val moviesList = Pager(PagingConfig(1)) {
    PopularMovieSource(repository)
}.flow.cachedIn(viewModelScope)

//Api
val detailsMovie = MutableLiveData<DetailsResponse>()
fun loadDetailsMovie(id: Int) = viewModelScope.launch {
    loading.postValue(true)
    val response = repository.getMovieDetails(id)
    if (response.isSuccessful) {
        detailsMovie.postValue(response.body())
    }
    loading.postValue(false)
}

My Repo

  class MovieShowRepository @Inject constructor(val apiService : ApiService){
  suspend fun getPopularMovie(page : Int) = apiService.getPopularMovie()
  suspend fun getMovieDetails(id:Int) = apiService.getMovieDetails(id)

You can see all the rest of my codes in my repo. When my app runs I don’t get any error but it is not showing in any yield. When I examine different repos, I see that the application works in projects with the same code lines as me, but it does not work in my project, thank you very much if you help.

>Solution :

Wrong:

private fun loadingData() {
    movieAdapter = PopularMovieAdapter()
    lifecycleScope.launch {
        viewModel.moviesList.collect { pagingData ->
            movieAdapter.submitData(pagingData)
        }
    }
}

private fun setUpRv() {
    movieAdapter = PopularMovieAdapter() // create a new adapter?
    binding.recyclerView.apply {
        layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
        adapter = movieAdapter
        setHasFixedSize(true)
    }
}

Correct:

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

    setUpRv() // 1st - setup RV
    loadingData() // 2nd - load data
}


private fun loadingData() {
    lifecycleScope.launch {
        viewModel.moviesList.collect { pagingData ->
            movieAdapter.submitData(pagingData)
        }
    }
}

In your code, the loadingData() function is called before the setUpRv() function. Therefore, when setUpRv() is called, the movieAdapter is created with default values instead of the current data from pagingData.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading