【发布时间】:2022-10-04 19:35:26
【问题描述】:
我正在制作一个电影应用程序,在单击类型按钮时,它应该使用不同发送的数据进行 api 调用。 即,每当用户单击系列或电影按钮时,它应该使用该特定参数进行 API 调用。
由于我使用 Android Paging3 进行分页。将加载初始数据。 但问题是当我单击电影或系列按钮时,我需要使用新参数和起始页码重新启动 PagingSource。 但是在 viewmodel 中调用分页源不会触发任何事情。
我需要一种使用新参数调用 pagingSource 的方法,以便在发生分页之后,应该使用这些参数来完成。
我的寻呼源
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)
}
}
}
这里的 searchQuery 和 searchType 参数是要改变的。 因此,每当更改时,我都需要调用新的寻呼源。 那就是问题所在
分页存储库
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
}
}
视图模型
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)
}
}
主要活动
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)
}
}
}
有人可以帮忙吗,因为我对 paging3 比较陌生,这似乎很混乱。 adapter.refresh() 或 adapter.retry() 似乎都不适用于新变量。 任何形式的建议或改进将不胜感激。 谢谢
【问题讨论】:
标签: android kotlin android-paging-3