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.
@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.
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
.