Paging
Paging可依照設定的需求來加載數據,減少網路和系統的使用。
DataSource:負責加載網路或資料庫的數據。
1.ItemKeyedDataSource:數據的Key有連續性,根據數據的Key取得資料(網路數據)。
2.PageKeyedDataSource:數據來源已有分頁功能,根據每頁的Key取得資料(網路數據)。
3.PositionalDataSource:根據RecyclerView的position取得資料(本地數據)。
DataSource.Factory<Int, Girl>():繼承DataSource.Factory有toLiveData方法。
PagedList.Config.Builder():創建設置讀取資料的時機。
toLiveData("PagedList.Config"):設置加載數據並將資料轉成LiveData。
PagedListAdapter:數據發生變化會計算數據的差異,通知RecyclerView更新數據。
submitList:將數據給RecyclerView。
導入Paging、Glide顯示圖片
implementation "androidx.fragment:fragment-ktx:1.2.5"
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
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>)
DataSource
class GirlDataSource : PageKeyedDataSource<Int, Girl>() {
private val myService by lazy { RetrofitUtil.instance.getService(MyService::class.java) }
var page = 1
//初始讀取資料
override fun loadInitial(
params: LoadInitialParams<Int>, callback: LoadInitialCallback<Int, Girl>
) {
CoroutineScope(Dispatchers.IO).launch {
val models = myService.getPage(page).data
callback.onResult(models, null, page)
}
}
//下一頁
override fun loadAfter(params: LoadParams<Int>, callback: LoadCallback<Int, Girl>) {
++page
CoroutineScope(Dispatchers.IO).launch {
val models = myService.getPage(page).data
callback.onResult(models, page)
}
}
override fun loadBefore(params: LoadParams<Int>, callback: LoadCallback<Int, Girl>) {
}
}
DataSourceFactory
class GirlDataSourceFactory : DataSource.Factory<Int, Girl>() {
override fun create(): DataSource<Int, Girl> {
return GirlDataSource()
}
}
設置配置跟創建PagedList
class GirlViewModel : ViewModel() {
private val config = PagedList.Config.Builder()
.setPrefetchDistance(2)
.build()
private val pagedListModel = MyDataSourceFactory().toLiveData(config)
fun reset() {
pagedListModel.value?.dataSource?.invalidate()
}
}
PagedListAdapter
class GirlAdapter : PagedListAdapter<Girl, GirlAdapter.GirlViewHolder>(INDIFFERENCE) {
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): GirlViewHolder {
context = parent.context
return GirlViewHolder(
LayoutInflater.from(context).inflate(R.layout.item_girl, parent, false)
)
}
override fun onBindViewHolder(holder: GirlViewHolder, position: Int) {
val girl = getItem(position)
girl?.also {
holder.des.text = it.desc
Glide.with(context)
.load(it.images[0])
.into(holder.photo)
}
}
inner class GirlViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val des: TextView = itemView.girl_info
val photo: ImageView = itemView.girl_photo
}
}
MainActivity
class MainActivity : AppCompatActivity() {
private val girlViewModel by viewModels<GirlViewModel>()
private val girlAdapter = GirlAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recycler.apply {
layoutManager = LinearLayoutManager(this@MainActivity)
adapter = girlAdapter
}
girlViewModel.pagedListModel.observe(this, Observer {
girlAdapter.submitList(it)
})
}
fun refresh(view: View) {
girlViewModel.reset()
}
}