A Kotlin Multiplatform library for pagination.
This library is used on Kotlin Multiplatform that targets Android and iOS.
Check the table below for the compatibilty across versions
Library | Kotlin | Paging |
---|---|---|
0.3.1 | 1.4.10 | 3.0.0-alpha07 |
0.3.0 | 1.4.0 | 3.0.0-alpha06 |
0.2.0 | 1.3.70 | 3.0.0-alpha01 |
0.1.+ | 1.3.70 | 2.1.1 |
0.1.0 | 1.3.61 | 2.1.1 |
Add the jcenter repository on your Project-level gradle
allprojects {
repositories {
...
jcenter()
}
}
On the module-level, add the library as an api
dependency. The library needs to be propagated to the platforms.
On Android, it's automatically handled by Gradle. It will also add androidx.paging:paging-runtime:3.0.0-alpha06
as a transitive depenency
kotlin {
...
sourceSets["commonMain"].dependencies {
api("com.kuuuurt:multiplatform-paging:0.3.0")
}
}
On iOS, you have to export it on your targets
If you're using the target shortcut for iOS:
kotlin {
...
targets.named<KotlinNativeTarget>("iosX64") {
binaries.withType<Framework>().configureEach {
export("com.kuuuurt:multiplatform-paging-iosX64:0.3.0")
}
}
targets.named<KotlinNativeTarget>("iosArm64") {
binaries.withType<Framework>().configureEach {
export("com.kuuuurt:multiplatform-paging-iosArm64:0.3.0")
}
}
}
If you're using a switching mechanism:
kotlin {
...
val isDevice = System.getenv("SDK_NAME")?.startsWith("iphoneos") == true
val pagingIos: String
val iosTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget
if (isDevice) {
iosTarget = ::iosArm64
pagingIos = "com.kuuuurt:multiplatform-paging-iosArm64:0.3.0"
} else {
iosTarget = ::iosX64
pagingIos = "com.kuuuurt:multiplatform-paging-iosX64:0.3.0"
}
iosTarget("ios") {
...
binaries.withType<Framework>().configureEach {
export(pagingIos)
}
}
}
Multiplatform paging exposes paginators which you can use in your multiplatform code to have common pagination on Android and iOS.
class MyMultiplatformController {
val pager = Pager<Int, String>(
clientScope = coroutineScope,
config = PagingConfig(
pageSize = 10,
enablePlaceholders = false // Ignored on iOS
),
initialKey = 1, // Key to use when initialized
prevKey = { _, _ -> null }, // Key for previous page, null means don't load previous pages
nextKey = { items, currentKey -> currentKey + 1 } // Key for next page. Use `items` or `currentKey` to get it depending on the pagination strategy
getItems = { startAt, size -> ... } // How you will get the items (API Call or Local DB)
)
val pagingData: CommonFlow<PagingData<String>>
get() = pager.pagingData
.cachedIn(clientScope) // cachedIn from AndroidX Paging. on iOS, this is a no-op
.asCommonFlow() // So that iOS can consume the Flow
}
On Android, multiplatform paging uses Android Architecture Component's Paging library and exposes pagedList
as a Flow<androidx.paging.PagedList<T>>
which can be observed and submitted onto the PagedListAdapter
.
class MyFragment : Fragment() {
val myMultiplatformController = MyMultiplatformController()
val myPagingDataAdapter = MyPagingDataAdapter()
override fun onViewCreated(...) {
super.onViewCreated(...)
myMultiplatformController.pager.pagingData
.onEach { myPagingDataAdapter.submitData(it) }
.launchIn(viewLifecyleOwner.lifecyclerScope)
}
}
On iOS, it exposes pagedList
as a Flow<List<T>>
which can be observed and rendered to a UITableView
class MyViewController UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
let myMultiplatformController = MyMultiplatformController()
private var data: [T] = []
private var count: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// setup...
myMultiplatformController.paginator.pagedList.watch { [unowned self] nullableArray in
guard let list = nullableArray?.compactMap({ $0 as? T }) else {
return
}
self.data = list
self.count = list.count
self.tableView.reloadData()
}
}
}
Disclaimer: I'm not an iOS developer and this is what I was able to make of. If someone has a better example, contributions are welcome!
- Kurt Renzo Acosta - [email protected]
Feel free to dive in! Open an issue or submit PRs.
Apache-2.0 © Kurt Renzo Acosta