Android RecyclerView AsyncListUtil手动刷新fillData,kotlin
    implementation 'com.github.bumptech.glide:glide:4.15.1'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.OnScrollListener
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
class MainActivity : AppCompatActivity() {
    companion object {
        const val TAG = "fly"
    }
    private var mRecyclerView: RecyclerView? = null
    private val mItems = ArrayList<MyData>()
    private var fromPos: Int = 0
    private var toPos: Int = 0
    private var startPosition: Int = 0
    private var itemCount: Int = 0
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mRecyclerView = findViewById(R.id.recycler_view)
        mRecyclerView?.layoutManager = GridLayoutManager(this, 3).apply {
            orientation = GridLayoutManager.VERTICAL
        }
        repeat(1000) {
            val data = MyData("-", "-", R.drawable.ic_launcher_background)
            mItems.add(data)
        }
        val mAdapter = MyAdapter(mItems)
        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
                ) {
                    this@MainActivity.startPosition = startPosition
                    this@MainActivity.itemCount = itemCount
                    Log.d(TAG, "onFillData $startPosition $itemCount")
                    fillData(startPosition, itemCount)
                }
                override fun onVisibleRange(fromPos: Int, toPos: Int) {
                    this@MainActivity.fromPos = fromPos
                    this@MainActivity.toPos = toPos
                }
                override fun refreshData(): Int {
                    return mItems.size
                }
            })
        mRecyclerView?.addOnScrollListener(object : OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                mRecyclerViewUtil?.onRangeChanged()
            }
        })
        //打开即滚到到最后
        mRecyclerView?.scrollToPosition(mAdapter.itemCount - 1)
        val fab: FloatingActionButton = findViewById(R.id.fab)
        fab.setOnClickListener { view ->
            Snackbar.make(
                view,
                "视野:$fromPos->$toPos\n已加载:$startPosition-$itemCount",
                Snackbar.LENGTH_LONG
            ).setAction(
                "点击这里加载视野外:${startPosition - itemCount}-$itemCount",
                object : View.OnClickListener {
                    override fun onClick(v: View?) {
                        fillData(startPosition - itemCount, itemCount)
                    }
                }).show()
        }
    }
    fun fillData(start: Int, count: Int) {
        var pos: Int
        for (i in 0 until count) {
            pos = start + i
            var data = mItems[pos]
            data.pos = "pos:$pos"
            data.text = "text:$pos"
            data.resId = R.drawable.ic_launcher_foreground
        }
        Log.d(TAG, "已加载->$start $count")
        runOnUiThread { mRecyclerView?.adapter?.notifyDataSetChanged() }
    }
}<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity" />
    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="end|bottom"
        android:layout_margin="16dp"
        android:contentDescription="更新"
        android:src="@android:drawable/ic_menu_add" />
</FrameLayout>import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
class MyAdapter(private var items: ArrayList<MyData>) : RecyclerView.Adapter<MyViewHolder>() {
    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 onBindViewHolder(holder: MyViewHolder, position: Int) {
        Glide.with(holder.itemView.context).load(items?.get(position)?.resId).into(holder.image)
        holder.pos.text = items?.get(position)?.pos
        holder.text.text = items?.get(position)?.text
    }
    override fun getItemCount(): Int {
        return items?.size!!
    }
}
class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val image: ImageView = itemView.findViewById(R.id.image)
    val pos: TextView = itemView.findViewById(R.id.pos)
    val text: TextView = itemView.findViewById(R.id.text)
}
data class MyData(var pos: String, var text: String, var resId: Int?)<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingTop="5dp"
    android:paddingBottom="5dp">
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/pos"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="-"
        android:textColor="@android:color/darker_gray"
        android:textSize="15dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/image" />
    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="-"
        android:textColor="@color/black"
        android:textSize="12dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/pos" />
</androidx.constraintlayout.widget.ConstraintLayout>
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() {
            Log.d(MainActivity.TAG, "onDataRefresh")
        }
        override fun onItemLoaded(position: Int) {
            Log.d(MainActivity.TAG, "onItemLoaded $position")
        }
    }
    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
        }
    }
}Android RecyclerView paging/pager/page implements based on AsyncListUtil,kotlin_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/130874429



















