I Did this. Is this Good?
I want to Make a Paginator class or Something injectable and generic and only once. and inject in Repo and using it.
I don’t know too much About Generic Type. I want to make it generic and Using It for Any Type of List any type of Document Snapshots?
fun <T> DefaultPaginator(
collectionReference: CollectionReference?,
lastItem: DocumentSnapshot? = null,
onLoading: () -> Unit,
onSuccess: (List<T>) -> Unit,
onError: (Throwable) -> Unit,
myClassToObject: Class<T>,
) {
onLoading()
collectionReference
?.orderBy("timestamp", Query.Direction.DESCENDING)
?.startAfter(lastItem)
?.get()
?.addOnSuccessListener { documents ->
val nextList = documents?.map {
it.toObject(myClassToObject)
}
onSuccess(nextList!!)
}
?.addOnFailureListener { error ->
onError(error)
}
}
and In Repo
var lastNewsVisibleItem: DocumentSnapshot?
and In RepoImpl
override var lastNewsListVisibleItem: DocumentSnapshot? = null
// News
override fun getNewsList(): Flow<NewsState<List<NewsModel>>> = callbackFlow {
trySend(NewsState.Loading)
newsColRef
?.orderBy("timestamp", Query.Direction.DESCENDING)
?.limit(4)
?.get()
?.addOnSuccessListener { documents -> //, error ->
lastNewsListVisibleItem = documents.documents[documents.size() - 1]
println("Last Visible Item Index in getNewsList(): $lastNewsListVisibleItem")
val news = documents.map {
it.toObject(NewsModel::class.java)
}
trySend(NewsState.Success(news))
}
?.addOnFailureListener { error ->
trySend(NewsState.Failed(error))
}
awaitClose {
close()
}
}
override fun <T> getNextList(
collectionReference: CollectionReference?,
lastItem: DocumentSnapshot?,
myClassToObject: Class<T>
): Flow<NewsState<List<T>>> {
return callbackFlow {
if (lastNewsListVisibleItem != null) {
if (lastNewsListVisibleItem?.exists()!!) {
DefaultPaginator(
collectionReference = collectionReference,
lastItem = lastItem,
onLoading = {
trySend(NewsState.Loading)
},
onSuccess = { nextList ->
trySend(NewsState.Success(nextList))
},
onError = { error ->
trySend(NewsState.Failed(error))
},
myClassToObject = myClassToObject
)
}
}
awaitClose {
close()
}
}
}
In ViewModel
fun getNextNewsList() {
viewModelScope.launch {
delay(2000)
newsRepository
.getNextList<NewsModel>(
collectionReference = newsRepository.newsColRef,
lastItem = newsRepository.lastNewsListVisibleItem,
myClassToObject = NewsModel::class.java
)
.collectLatest { result ->
when (result) {
is NewsState.Loading -> {
nextNewsListStatus = Status.Loading
}
is NewsState.Success -> {
_newsList.value = result.data
nextNewsListStatus = Status.SUCCESS
}
is NewsState.Failed -> {
nextNewsListStatus = Status.FAILED
errorMsg.value = result.error.localizedMessage ?: ""
}
}
}
}
}
In UI
LazyColumn {
items(newsList.size) { index ->
val item newsList[index]
if (
index == newsList.lastIndex - 1
&& newsCategoryStatus.isEmpty()
) {
newsViewModel.getNextNewsList()
}
NewsItem(item)
}
if (newsViewModel.nextNewsListStatus == Status.Loading) {
item {
Row(
horizontalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxWidth()
) {
CircularProgressIndicator()
}
}
}
}
and Using In ViewModel’s function, Is this Good?
I want make a Pagination class or something and make it Injectable using koin and using It.
Abdullah Hameed is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.