iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 14
1
Mobile Development

Kotlin Android Jetpack 系列 第 14

{Day14}Paging

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()
    }
}


上一篇
{Day13}ViewBinding
下一篇
{Day15}Paging3
系列文
Kotlin Android Jetpack 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言