不总是。
如果您正在使用提供良好支持的其他 Android 架构组件或库,在大多数情况下,DataSource.Factory 将作为方法调用的结果交付,例如 Room 数据库。
如果您真的想要一个非常通用的并且对反射没有问题:
class GenericFactory<K, R>(private val kClass: KClass<DataSource<K, R>>) : DataSource.Factory<K, R>() {
override fun create(): DataSource<K, R> = kClass.java.newInstance()
}
您的示例显示了将 DataSource 公开为 LiveData 的 DataSource.Factory。这仅在特定情况下是必需的,例如,当 DataSource 持有 API 调用的重试方法时。在其他情况下,您的 DataSource.Factory 将像 DataSource 中的 3 行一样简单:
class MySimpleDataSource<R> : PageKeyedDataSource<String, R>() {
override fun loadBefore(params: LoadParams<String>,
callback: LoadCallback<String, R>) {
// do your thing
}
override fun loadAfter(params: LoadParams<String>,
callback: LoadCallback<String, R>) {
// do your thing
}
override fun loadInitial(params: LoadInitialParams<String>,
callback: LoadInitialCallback<String, R>) {
// do your thing
}
class Factory<R> : DataSource.Factory<String, R>() {
override fun create(): DataSource<String, R> = MySimpleDataSource<R>()
}
}
我猜自定义 DataSource.Factory 最常见的情况是分页的 REST API 调用。在这种情况下,您可以只实现一个通用数据源和一个接收请求对象和响应回调作为 lambda 的 DataSource.Factory。
data class MyCollection<R>(
var items: List<R>,
var nextPageToken: String
)
data class MyData(
var title: String = ""
)
abstract class SomeLibraryPagedClientRequest<R> {
abstract fun setNextPageToken(token: String?): SomeLibraryPagedClientRequest<R>
abstract fun enqueue(callback: (response: Response<R>) -> Unit): Unit
}
class MyRestApiDataSource(
private val request: SomeLibraryPagedClientRequest<MyData>,
private val handleResponse: (Response<R>) -> Unit
) : ItemKeyedDataSource<String, MyData>() {
var nextPageToken: String = ""
override fun getKey(item: MyData): String = nextPageToken
override fun loadBefore(params: LoadParams<String>, callback: LoadCallback<MyData>) {
}
override fun loadInitial(params: LoadInitialParams<String>, callback: LoadInitialCallback<MyData>) {
request.setNextPageToken(params.requestedInitialKey).enqueue { data ->
nextPageToken = response.data.nextPageToken
if(response.isSucefull) callback.onResult(response.data.items)
handleResponse.invoke(response)
}
}
override fun loadAfter(params: LoadParams<String>, callback: LoadCallback<MyData>) {
request.setNextPageToken(params.key).enqueue { response ->
nextPageToken = response.data.nextPageToken
if(response.isSucefull) callback.onResult(response.data.items)
handleResponse.invoke(response)
}
}
class Factory<R>(
private val request: SomeLibraryPagedClientRequest<MyData>,
private val handleResponse: (Response<R>) -> Unit
) : DataSource.Factory<String, R>() {
override fun create(): DataSource<String, R> = MySimpleDataSource<R>()
}
}