iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
1
Mobile Development

Kotlin Android Jetpack 系列 第 15

{Day15}Paging3

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


上一篇
{Day14}Paging
下一篇
{Day16}WorkManager
系列文
Kotlin Android Jetpack 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言