In Android development, a PagingAdapter is part of the Paging library, which is a component of Jetpack designed to handle large datasets in a RecyclerView efficiently. The Paging library helps load data incrementally, reducing memory consumption and improving the responsiveness of the application. In onelib, there is already a base for the paging adapter and there is an extension function to handle the state of LoadState. For example
Copy class TestPagingAdapter : BasePagingRecyclerAdapter < Movie , TestPagingAdapter . ViewHolder >() {
override fun getViewBinding (parent: ViewGroup , viewType: Int ): ViewBinding {
return ItemRecyclerBinding. inflate (LayoutInflater. from (parent.context), parent, false )
}
override fun onCreateViewHolder (
parent: ViewGroup ,
viewType: Int
): ViewHolder {
return ViewHolder ( getViewBinding (parent, viewType))
}
inner class ViewHolder (binding: ViewBinding ) : BaseAsyncItemViewHolder < Movie >( binding ) {
override fun bind ( data : Movie ) {
with (binding as ItemRecyclerBinding) {
tvTitle.text = data .title
}
}
}
}
And if you need the load state to take the loading down from the content, you can create a new xml file and create a class to handle the state. For example
Copy <? xml version = "1.0" encoding = "utf-8" ?>
< androidx.constraintlayout.widget.ConstraintLayout xmlns : android = "http://schemas.android.com/apk/res/android"
xmlns : app = "http://schemas.android.com/apk/res-auto"
android : layout_width = "match_parent"
android : layout_height = "wrap_content"
android : paddingTop = "18dp" >
< ProgressBar
android : id = "@+id/progress_bar"
android : layout_width = "wrap_content"
android : layout_height = "wrap_content"
android : indeterminateTint = "@color/black"
app : layout_constraintEnd_toEndOf = "parent"
app : layout_constraintStart_toStartOf = "parent"
app : layout_constraintTop_toTopOf = "parent" />
< TextView
android : id = "@+id/tv_error"
android : layout_width = "0dp"
android : layout_height = "wrap_content"
android : layout_marginHorizontal = "@dimen/dimen_20dp"
android : gravity = "center"
android : text = "@string/error"
android : textColor = "@color/black"
app : layout_constraintEnd_toEndOf = "parent"
app : layout_constraintStart_toStartOf = "parent"
app : layout_constraintTop_toTopOf = "parent" />
< androidx.appcompat.widget.AppCompatButton
android : id = "@+id/btn_retry"
android : layout_width = "wrap_content"
android : layout_height = "wrap_content"
android : text = "Retry"
app : layout_constraintStart_toStartOf = "parent"
app : layout_constraintEnd_toEndOf = "parent"
android : textAllCaps = "false"
android : textSize = "14sp"
android : textColor = "@color/white"
app : layout_constraintTop_toBottomOf = "@id/tv_error"
android : layout_marginTop = "10dp"
android : backgroundTint = "@color/black" />
</ androidx.constraintlayout.widget.ConstraintLayout >
Copy class TestLoadStateAdapter (
private val retry: () -> Unit
) : LoadStateAdapter < TestLoadStateAdapter . ViewHolder >() {
override fun onBindViewHolder (holder: TestLoadStateAdapter .ViewHolder, loadState: LoadState ) {
holder. bind (loadState)
}
override fun onCreateViewHolder (
parent: ViewGroup ,
loadState: LoadState
): TestLoadStateAdapter . ViewHolder {
return ViewHolder (
LayoutLoadStateAdapterBinding. inflate (
parent.context.layoutInflater,
parent,
false
)
)
}
inner class ViewHolder (
private val binding: LayoutLoadStateAdapterBinding
) : RecyclerView . ViewHolder (binding.root) {
fun bind (loadState: LoadState ) = with (binding) {
if (loadState is LoadState.Error) tvError.text = loadState.error.message
progressBar.isVisible = loadState is LoadState.Loading
tvError.isVisible = loadState is LoadState.Error
btnRetry.isVisible = loadState is LoadState.Error
btnRetry. onClick {
retry. invoke ()
}
}
}
Then, you can implement it in an Activity or Fragment. For example
Copy // submit data into adapter
viewModel.paging. observe ( this ) {
mAdapter. submitData (lifecycle, it)
}
// handle loading or error
binding.rvMovie. apply {
adapter = mAdapter. withLoadStateHeaderAndFooter (
header = TestLoadStateAdapter { mAdapter. retry () },
footer = TestLoadStateAdapter { mAdapter. retry () }
)
}
// handle state
mAdapter. loadStateListener (
notLoading = { binding.stateView. showContent () },
loading = { binding.stateView. showLoading () },
endOfPaging = { binding.stateView. showContent () }
)