I really enjoy it when I can design a class that should keep logic. It feels like pure engineering. You can't do this perfectly from the first time; you have to iterate, step by step.
What I did:
I worked on the implementation of the pagination for articles. In the Android world, Google provides the Pagination Library to solve this kind of task. Every time I tried to integrate it, I had a lot of trouble. It's always a pain. So, for this project, I decided to make it simpler.
The idea of pagination is very simple: you have a data source, and at some point, you need to load a new portion of data, called a new page. Since it's just logic, we can keep it in a pure Kotlin file. I design a simple Pagination
class that holds this logic. In the constructor, it accepts a data source
, a callback onNewPortionLoaded
that notifies when a new portion is loaded, and a scope
that to launch coroutines. The implantation is pretty simple:
class Pagination<T>(
private val source: suspend (page: Int) -> List<T>,
private val onNewPortionLoaded: (data: List<T>) -> Unit,
private val scope: CoroutineScope,
startPosition: Int = -1,
) {
private var startPage: Int = startPosition
fun startLoading() {
loadNewPortion()
}
fun loadNewPortion() {
scope.launch(Dispatchers.IO) {
startPage += 1
val newPortion = source(startPage)
launch(Dispatchers.Main) {
onNewPortionLoaded(newPortion)
}
}
}
}
I made this class generic so that it can be used on other screens. Now, If you want to use it in a viewModel
or ScreenModel
in the context of KMM, you just create an instance of the class, reference its methods, and call startLoading()
and loadNewPortion()
in appropriate places.
class HomeScreenModel(
private val getArticlesUseCase: GetArticleUseCase,
private val stringProvider: StringProvider
) : ScreenModel {
private val pagination: Pagination<Article> = Pagination(
source = ::loadNext,
onNewPortionLoaded = ::onNewPortionLoaded,
scope = screenModelScope,
)
init {
pagination.startLoading()
}
private suspend fun loadNext(page: Int): List<Article> {
return getArticlesUseCase(GetArticlesParams(page = page))
}
private fun onNewPortionLoaded(newPortion: List<Article>) {
_isLoading.value = false
_articlesState.value += newPortion.map { it.mapToArticleUi(stringProvider) }
}
fun loadMoreArticles() {
_isLoading.value = true
pagination.loadNewPortion()
}
}
What I will do:
- Add Detekt(a static code analysis tool) to the project.
- Update README file with description of project.
- Create a GitHub project to manage the tasks for future collaboration.
- Fix comment element
- Implementation of WebView to display stub content
If you want to join the project, just leave a comment here, or write a message in LinkedIn.
What help I'm looking for:
Designer (create design of application in Figma)
Android/KMM developer
Any other help related to the project.
My timeline:
Day 1. Deep breath and dive.
Day 2. Networking layer.
Day 3. Loading of articles.
Day 4. ArticleItem.
Day 5. Localization.
Day 6. Work on Sunday.
Day 7. First week.
Day 8. Enjoying coding.
Day 9. Expect/actual.
Day 10. TODOs.
Day 11. Friday evening.
Day 12. Frustration.
Day 13. Blocker
Day 14. Monday
Day 15. Reactions
Day 16. Feed
Day 17. stringWithFormat
Day 18. Comment
Day 19. 1 percent
Day 20. A bit of progress
See you tomorrow.
Top comments (0)