我想从我们的后端服务器中获取20个Job项目。我需要获取的api是基于位置的。这就是为什么我使用PositionalDataSource
我使用Rxjava的streamData和LiveData将数据连接到UI。我需要每次滚动获取20个项目。因此,我使用PositionalDataSource进行检索。实际上,后端开发人员生成的Api是基于位置的。但是我在recyclerView中看不到任何值。
JobService.kt
@GET(Constants.API_JOB_LIST)
fun getJobPost(
@Query("offset") numberOfItemPerRequest: Int
): Observable<Response<JobResponse>>
RetrofitBuilder.kt
fun retrofit(baseUrl: String): Retrofit = Retrofit.Builder()
.client(getOkHttpClient())
.baseUrl(baseUrl)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
private fun getOkHttpClient(): OkHttpClient {
return OkHttpClient().newBuilder()
.connectTimeout(3, TimeUnit.SECONDS)
.readTimeout(3, TimeUnit.SECONDS)
.writeTimeout(3, TimeUnit.SECONDS)
.addInterceptor(headersInterceptor)
.addInterceptor(loggingInterceptor)
.build()
}
ApiUtils.kt
val loggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
val headersInterceptor = Interceptor {
val request = it.request()
it.proceed(
request.newBuilder()
.addHeader("Accept", "application/json")
.addHeader("Content-Type", "application/json")
.addHeader("api_key", "sr8fyw8hcow8efhisncsef0wefw9ef0swdcsopd")
.build()
)
}
ApiFactory.kt
val jobListApi: JobService = RetrofitBuilder
.retrofit(Constants.BASE_URL)
.create(JobService::class.java)
JobResponse.kt
data class JobResponse(
@field:SerializedName("msg") val msg: String? = null,
@field:SerializedName("data") val data: List<Job?>? = null,
@field:SerializedName("status") val status: Int? = null
)
JobDataSource.kt
class JobDataSource(
private val jobService: JobService,
private val compositeDisposable: CompositeDisposable
): PositionalDataSource<Job>() {
companion object {
private const val POSITION_OF_JOB_POST = 0
}
override fun loadInitial(params: LoadInitialParams, callback: LoadInitialCallback<Job>) {
val initialJobList = jobService.getJobPost(POSITION_OF_JOB_POST)
compositeDisposable += initialJobList
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
if (it.isSuccessful) {
val jobList = it?.body()?.data!!
callback.onResult(
jobList,
computeInitialLoadPosition(params, jobList.size),
jobList.size
)
} else {
// ... statusCode = it.code()
}
}, {
if(it is IOException) {
// ... No Internet
} else {
// ... Converter Exception(Json Parsing error)
}
})
}
override fun loadRange(params: LoadRangeParams, callback: LoadRangeCallback<Job>) {
val initialJobList = jobService.getJobPost(POSITION_OF_JOB_POST)
compositeDisposable += initialJobList
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
if (it.isSuccessful) {
callback.onResult(it?.body()?.data!!)
} else {
// ... statusCode = it.code()
}
}, {
if(it is IOException) {
// ... No Internet
} else {
// ... Converter Exception(Json Parsing error)
}
})
}
}
JobDataSourceFactory.kt
class JobDataSourceFactory(
private val jobService: JobService,
private val compositeDisposable: CompositeDisposable
): DataSource.Factory<Int, Job>() {
override fun create() = JobDataSource(jobService, compositeDisposable)
}
JobDataProvider.kt
class JobDataProvider(
private val jobService: JobService,
private val compositeDisposable: CompositeDisposable
) {
companion object {
private const val PAGE_SIZE = 20
private const val PREFETCH_DISTANCE = 20
}
fun getJobs(): Observable<PagedList<Job>> {
val config = PagedList.Config.Builder()
.setPageSize(PAGE_SIZE)
.setInitialLoadSizeHint(PAGE_SIZE)
.setPrefetchDistance(PREFETCH_DISTANCE)
.setEnablePlaceholders(true)
.build()
return RxPagedListBuilder(
JobDataSourceFactory(jobService, compositeDisposable),
config
).buildObservable()
}
}
JobBoardViewModel.kt
class JobBoardViewModel : BaseViewModel() {
var jobList: LiveData<PagedList<Job>> = MutableLiveData()
fun getJobList() {
val observableList: Observable<PagedList<Job>> = JobDataProvider(
ApiFactory.jobListApi,
compositeDisposable
).getJobs()
jobList = LiveDataReactiveStreams.fromPublisher(observableList.toFlowable(BackpressureStrategy.BUFFER))
}
}
JobFragment.kt
viewModel.jobList.observe(viewLifecycleOwner, Observer {
jobAdapter.submitList(it)
})