I am making a movie app in which on click of a button of type , It should make an api call with a diffrent sent of data. Ie whenever the user clicks on Series or Movie button , It should make an API call with that specific parameter.
Since I have used Android Paging3 for paging. The Initial data will be loaded. But the problem is when I click the Movie or Series button , I need to restart the PagingSource with new parameters and starting page number. But calling the paging source in viewmodel is not triggering anything .
I need a way to call the pagingSource with new Parameters , so that after that if paging happens , it should be done with those parameters.
My Paging Source
class MoviePagingSource(
private val searchQuery: String,
private val searchType : String,
private val movieRepository: MovieRepository
) : PagingSource<Int , Movie>() {
private val INITIAL_PAGE = Constants.INITIAL_PAGE_NUMBER
override fun getRefreshKey(state: PagingState<Int, Movie>): Int? {
return state.anchorPosition?.let {
state.closestPageToPosition(it)?.prevKey?.plus(1) ?: state.closestPageToPosition(it)?.nextKey?.minus(1)
}
}
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Movie> {
return try {
val position = params.key ?: INITIAL_PAGE
val response = movieRepository.searchMovie(searchQuery , position , searchType)
val endOfPaginationReached = (response.data?.result == null)
LoadResult.Page(
data = response.data!!.result,
prevKey = if(position == INITIAL_PAGE) null else position.minus(1),
nextKey = if (endOfPaginationReached) null else position.plus(1)
)
}catch (e : Exception){
LoadResult.Error(e)
}
}
}
Here the searchQuery and the searchType parameters are the ones that would be changed. Hence whenever that is changed , I need to call a new paging source. That is the problem
PagingRepository
class MoviePagingRepository @Inject constructor(
private val movieRepository: MovieRepository
) {
private var pagingConfig : PagingConfig
init {
pagingConfig = PagingConfig(pageSize = Constants.PAGE_SIZE , maxSize = Constants.MAX_PAGE_COUNT)
}
fun getMovies(searchQuery: String, movieType : String, )
:LiveData<PagingData<Movie>> {
return Pager(config = pagingConfig , pagingSourceFactory = {MoviePagingSource(searchQuery , movieType , movieRepository)}).liveData
}
}
ViewModel
class HomeViewModel @Inject constructor(
private val moviePagingRepository: MoviePagingRepository,
private val movieRepository: MovieRepository
) : ViewModel(){
var movieList : LiveData<PagingData<Movie>> = MutableLiveData()
fun searchMovie(searchQuery : String , movieType : String) {
movieList = moviePagingRepository.getMovies(searchQuery , movieType)
}
}
MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
init()
}
private fun init(){
movieViewModel = ViewModelProvider(this)[HomeViewModel::class.java]
movieAdapter = MovieAdapter(movieViewModel)
movies_recyclerview.apply {
layoutManager = GridLayoutManager(context , Constants.COLUMN_COUNT)
setHasFixedSize(true)
adapter = movieAdapter.withLoadStateFooter(
footer = LoaderAdapter()
)
}
//This triggers the paging
searchMovie(currentSearchQuery, currentMovieType)
//This observes.
observeViewModels()
}
private fun searchMovie(searchQuery : String , movieType : String){
movieViewModel.searchMovie(searchQuery , movieType)
}
private fun observeViewModels(){
movieViewModel.movieList.observe(this) {
movieAdapter.submitData(lifecycle, it)
}
//This is triggered when I click on any movie type ( series , movie etc.)
// This triggers the viewmodel method again. but apparently nothing happens
movieViewModel.getMovieType().observe(this) { movieType ->
searchMovie(currentSearchQuery, currentMovieType)
}
}
}
Can someone help on this , Since I am relatively new to paging3 and this seems very confusing. adapter.refresh() or adapter.retry() both seem to not work with new variables. Any sort of suggestion or improvement would be appreciated. Thank you