Android RecyclerView paging/pager/page implements based on AsyncListUtil,kotlin
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : AppCompatActivity() {
companion object {
val TAG = "test-log"
}
//假设已经知道全量数据,后续的分段是把源数据一片一片的截出来,装到新的分页数据集里面
val ITEMS = ArrayList<MyData>()
var COUNT = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var mRecyclerView: RecyclerView = findViewById<RecyclerView>(R.id.recycler_view)
mRecyclerView?.layoutManager = GridLayoutManager(this, 3).apply {
orientation = GridLayoutManager.VERTICAL
}
val mAdapter = MyAdapter()
mRecyclerView?.adapter = mAdapter
MyPagingRecyclerViewUtil.PAGE_SIZE = 50
var mRecyclerViewUtil = MyPagingRecyclerViewUtil(mRecyclerView!!,
object : MyPagingRecyclerViewUtil.PagingListener {
override fun onFillData(
data: Array<out Any>, startPosition: Int, itemCount: Int
) {
Log.d(TAG, "onFillData $startPosition $itemCount")
fillData(startPosition, itemCount)
}
override fun onVisibleRange(fromPos: Int, toPos: Int) {
Log.d(TAG, "onVisibleRange $fromPos $toPos ${ITEMS.size}")
}
override fun refreshData(): Int {
return ITEMS.size
}
})
mRecyclerView?.addOnScrollListener(object : OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
mRecyclerViewUtil?.onRangeChanged()
}
})
CoroutineScope(Dispatchers.IO).launch {
repeat(Int.MAX_VALUE) {
ITEMS.clear()
COUNT = (200..400).random()
//COUNT=201
for (i in 0 until COUNT) {
var data = MyData("-$COUNT-")
ITEMS.add(data)
}
//触发onFillData()
mRecyclerViewUtil?.refresh()
delay(20) //如果不时延,新数据不能实时更新到UI
runOnUiThread {
mAdapter.onChange(ITEMS)
//RecyclerView启动后默认滚到最底部
//mRecyclerView?.scrollToPosition(mAdapter.getItemCount() - 1)
}
//模拟下一批新数据在此时间后到
delay(5000)
}
}
}
fun fillData(startPosition: Int, itemCount: Int) {
var pos = 0
for (i in 0 until itemCount) {
pos = startPosition + i
ITEMS.set(pos, MyData("$startPosition $i -$COUNT ${System.currentTimeMillis()}"))
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" />
import android.util.Log
import androidx.annotation.UiThread
import androidx.annotation.WorkerThread
import androidx.recyclerview.widget.AsyncListUtil
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
class MyPagingRecyclerViewUtil(rv: RecyclerView, pagingListener: PagingListener) {
companion object {
var PAGE_SIZE = 200
}
private var mAsyncListUtil: AsyncListUtil<Any>? = null
init {
var viewCallback = PagingViewCallback(rv, pagingListener)
var dataCallback = PageingDataCallback(pagingListener)
mAsyncListUtil =
AsyncListUtil(Any().javaClass, PAGE_SIZE, dataCallback, viewCallback)
}
fun onRangeChanged() {
mAsyncListUtil?.onRangeChanged()
}
fun refresh(){
Log.d(MainActivity.TAG,"refresh")
mAsyncListUtil?.refresh()
}
private class PageingDataCallback(var listener: PagingListener) :
AsyncListUtil.DataCallback<Any>() {
//如果RecyclerView的数据源总长度发生变化,需要更新这个值,否则getItemRangeInto不会触发新的可视区域range更新。
override fun refreshData(): Int {
return listener?.refreshData() ?: 0
}
@WorkerThread
override fun fillData(data: Array<out Any>, startPosition: Int, itemCount: Int) {
listener?.onFillData(data, startPosition, itemCount)
}
}
private class PagingViewCallback(val recyclerView: RecyclerView, var listener: PagingListener) :
AsyncListUtil.ViewCallback() {
fun getOutRange(rv: RecyclerView, outRange: IntArray) {
outRange[0] = (rv.layoutManager as GridLayoutManager?)!!.findFirstVisibleItemPosition()
outRange[1] = (rv.layoutManager as GridLayoutManager?)!!.findLastVisibleItemPosition()
}
override fun getItemRangeInto(outRange: IntArray) {
getOutRange(recyclerView, outRange);
listener?.onVisibleRange(outRange[0], outRange[1])
}
override fun onDataRefresh() {
}
override fun onItemLoaded(position: Int) {
}
}
interface PagingListener {
@WorkerThread
fun onFillData(data: Array<out Any>, startPosition: Int, itemCount: Int) {
}
@UiThread
fun onVisibleRange(fromPos: Int, toPos: Int) {
}
fun refreshData(): Int {
return 0
}
}
}
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.annotation.MainThread
import androidx.recyclerview.widget.RecyclerView
class MyAdapter() : RecyclerView.Adapter<MyViewHolder>() {
var items: ArrayList<MyData>? = ArrayList()
@MainThread
fun onChange(items: ArrayList<MyData>) {
this.items = items
this.notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item, parent, false)
return MyViewHolder(view)
}
override fun getItemCount(): Int {
return items?.size!!
}
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
holder.pos.text = "$position"
holder.text.text = items?.get(position)?.str
}
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val pos: TextView = itemView.findViewById(R.id.pos)
val text: TextView = itemView.findViewById(R.id.text)
}
data class MyData(var str: String)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<TextView
android:id="@+id/pos"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="30dp" />
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textSize="12dp" />
</LinearLayout>
Android RecyclerView page/paging load,kotlin(3)_zhangphil的博客-CSDN博客基于Android官方Paging Library的RecyclerView分页加载框架我之前写了一篇RecyclerView分页加载机制的文章,是基于Android官方的AsyncListUtil实现的,详情见附录文章1。基于Android官方Paging Library的RecyclerView分页加载框架我之前写了一篇RecyclerView分页加载机制的文章,是基于Android官方的AsyncListUtil实现的,详情见附录文章1。【代码】Android Paging 3,kotlin(1)https://blog.csdn.net/zhangphil/article/details/130784241
Android Paging3/Page3 Cursor query segment photo into 3 grid RecyclerView,kotlin (2)_zhangphil的博客-CSDN博客基于Android官方Paging Library的RecyclerView分页加载框架我之前写了一篇RecyclerView分页加载机制的文章,是基于Android官方的AsyncListUtil实现的,详情见附录文章1。Android Paging Library是Android官方support。基于Android官方Paging Library的RecyclerView分页加载框架_android setmainthreadexecutor_zhangphil的博客-CSDN博客。https://blog.csdn.net/zhangphil/article/details/130751993
Android Paging 3 Flow or LiveData,kotlin(1)_zhangphil的博客-CSDN博客【代码】Android Paging 3,kotlin(1)https://blog.csdn.net/zhangphil/article/details/130735753
Android Room联合AsyncListUtil实现RecyclerView分页加载ORM数据_zhangphil的博客-CSDN博客Android Room联合AsyncListUtil实现RecyclerView分页加载ORM数据我之前写了一系列关于AsyncListUtil实现RecyclerView和ListView的分页加载机制和技术路线,见附录文章4,5。同时也写了一些列文章介绍Android官方推出的ORM数据库:Room技术,见附录文章1,2。现在结合Android分页加载框架AsyncListUtil,以及Anhttps://blog.csdn.net/zhangphil/article/details/78661838
基于Android官方AsyncListUtil优化改进RecyclerView分页加载机制(一)_recyclerview 分页机制_zhangphil的博客-CSDN博客基于Android官方AsyncListUtil优化改进RecyclerView分页加载机制(一)Android AsyncListUtil是Android官方提供的专为列表这样的数据更新加载提供的异步加载组件。基于AsyncListUtil组件,可以轻易实现常见的RecyclerView分页加载技术。AsyncListUtil技术涉及的细节比较繁复,因此我将分别写若干篇文章,分点、分解Asynchttps://blog.csdn.net/zhangphil/article/details/78603499