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