Paging3
Paging3大致上就是Paging的升級版,對Coroutines、Flow、LiveData、RxJava支持。
PagingSource(等於Paging的DataSource):負責加載網路或資料庫的數據。
Pager(等於Paging的LivePagedListBuilder)用Pager.flow創建Flow<PagingData<T>>。
PagingConfig(等於Paging的PagedList.Config):創建設置讀取資料的時機。
PagingDataAdapter(等於Paging的PagedListAdapter):數據發生變化會計算數據的差異,通知RecyclerView更新數據。
LoadResult.Page("數據","上一頁","下一頁"):創建LoadResult。
Pager("配置讀取時機","讀取的數據來源").flow:創建Flow<PagingData<T>>。
lifecycleScope:生命週期的範圍。
Flow<PagingData<T>>.collect:會回傳收集到的數據。
submitData:將數據給RecyclerView。
implementation "androidx.fragment:fragment-ktx:1.2.5"
implementation "androidx.paging:paging-runtime-ktx:3.0.0-alpha06"
implementation 'com.github.bumptech.glide:glide:4.2.0'
API
interface MyService {
@GET("v2/data/category/Girl/type/Girl/page/{page}/count/10")
suspend fun getPage(@Path("page")page: Int) : HttpResult
}
Model
data class HttpResult(val data: List<Girl>, val total_counts: Int)
data class Girl(val desc: String, val images: List<String>)
PagingSource
class GirlPagingSource(private val myService: GirlService) : PagingSource<Int, Girl>() {
var page = 1
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Girl> {
val position = params.key ?: page
val girl = myService.getGirl(position)
return try {
LoadResult.Page(
data = girl.data,
prevKey = null,
nextKey = if (girl.data.isEmpty()) null else position + 1
)
} catch (exception: IOException) {
LoadResult.Error(exception)
} catch (exception: HttpException) {
LoadResult.Error(exception)
}
}
}
設置PagingConfig跟創建PagingData
class GirlViewModel() : ViewModel() {
private val service by lazy {
RetrofitUtil.instance.getService(GirlService::class.java)
}
fun getData() : Flow<PagingData<Girl>>{
return Pager(
config = PagingConfig(
pageSize = 10,
enablePlaceholders = false
),
pagingSourceFactory = {GirlPagingSource(service)}
).flow
}
}
PagingDataAdapter
class GirlAdapter : PagingDataAdapter<Girl, GirlAdapter.GirlHolder>(INDIFFERENCE) {
private lateinit var context: Context
companion object {
val INDIFFERENCE = object : DiffUtil.ItemCallback<Girl>() {
override fun areItemsTheSame(oldItem: Girl, newItem: Girl): Boolean {
return oldItem == newItem
}
override fun areContentsTheSame(oldItem: Girl, newItem: Girl): Boolean {
return oldItem.images == newItem.images
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GirlHolder {
context = parent.context
return GirlHolder(LayoutInflater.from(context).inflate(R.layout.item_girl, parent, false))
}
override fun onBindViewHolder(holder: GirlHolder, position: Int) {
val girl = getItem(position)
holder.desc.text = girl?.desc
Glide.with(context)
.load(girl!!.images[0])
.into(holder.photo)
}
inner class GirlHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val desc: TextView = itemView.girl_info
val photo: ImageView = itemView.girl_photo
}
}
MainActivity
class MainActivity : AppCompatActivity() {
private var girlAdapter = GirlAdapter()
private val girlViewModel by viewModels<GirlViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recycler.apply {
adapter = girlAdapter
layoutManager = LinearLayoutManager(this@MainActivity)
addItemDecoration(DividerItemDecoration(this@MainActivity, DividerItemDecoration.VERTICAL))
}
search()
}
private fun search() {
lifecycleScope.launch {
girlViewModel.getData().collect {
girlAdapter.submitData(it)
}
}
}
fun reset(view: View) {
lifecycleScope.launch {
girlViewModel.getData().collect {
girlAdapter.submitData(it)
}
}
}
}