Android 显示“加载更多”按钮“回收器”视图的末尾

Android 显示“加载更多”按钮“回收器”视图的末尾,android,android-recyclerview,Android,Android Recyclerview,我有recyler视图,每页显示列表5项。但我不想要无休止的滚动或自动加载。但我想在列表的末尾显示加载更多按钮,当用户单击“加载更多”按钮时,将加载下一个数据。我已经证明了这一点。但问题是,当加载更多时,单击按钮加载更多混乱。并将最后一项从第一页复制到第二页 这是我的循环水 abstract class BaseAdapter<T, Y: BaseViewHolder>( private val isLoadMore: Boolean = false ): RecyclerV

我有recyler视图,每页显示列表5项。但我不想要无休止的滚动或自动加载。但我想在列表的末尾显示加载更多按钮,当用户单击“加载更多”按钮时,将加载下一个数据。我已经证明了这一点。但问题是,当加载更多时,单击按钮加载更多混乱。并将最后一项从第一页复制到第二页

这是我的循环水

abstract class BaseAdapter<T, Y: BaseViewHolder>(
    private val isLoadMore: Boolean = false
): RecyclerView.Adapter<BaseViewHolder>() {

    private var loadMoreListener = object : LoadMoreListener {
        override fun onLoadMore() {
            onLoad()
        }
    }

    private val listUpdateCallback = object :ListUpdateCallback{
        override fun onChanged(position: Int, count: Int, payload: Any?) {
            notifyItemRangeChanged(position, count, payload)
        }

        override fun onInserted(position: Int, count: Int) {
            notifyItemRangeInserted(position, count)
        }

        override fun onMoved(fromPosition: Int, toPosition: Int) {
            notifyItemMoved(fromPosition, toPosition)
        }

        override fun onRemoved(position: Int, count: Int) {
            notifyItemRangeRemoved(position, count)
        }
    }

    private val itemDiffCallback = object : DiffUtil.ItemCallback<T>(){
        override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
            return this@BaseAdapter.areContentsTheSame(oldItem, newItem)
        }

        override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
            return this@BaseAdapter.areItemsTheSame(oldItem, newItem)
        }
    }

    val data = AsyncListDiffer<T>(listUpdateCallback, AsyncDifferConfig.Builder<T>(itemDiffCallback).build())

    protected abstract fun areContentsTheSame(oldItem: T, newItem: T): Boolean
    protected abstract fun areItemsTheSame(oldItem: T, newItem: T): Boolean
    open fun updateList(items: List<T>) = data.submitList(items)
    open fun updateList(items: List<T>, callback: Runnable) = data.submitList(items, callback)
    override fun getItemCount(): Int = if (isLoadMore && data.currentList.isNotEmpty()) {
        data.currentList.size + 1
    } else {
        data.currentList.size
    }
    private fun getActual(index: Int): T? = if (isLoadMore && (index == items.size-1)) null else items[index]
    fun get(index: Int): T = if (isLoadMore && index == (data.currentList.size)) {
        data.currentList[index-1]
    } else {
        data.currentList[index]
    }
    val items: List<T> get() = data.currentList
    open fun onLoad(){ }

    @Suppress("UNCHECKED_CAST")
    override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
        if (isLoadMore && (position == items.size)){
            (holder as LoadMoreViewHolder).hideLoading()
            return
        }

        onBindHolder(holder as Y, position)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
        return if (viewType == -1) {
            val v = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_load_more_loading, parent, false)
            LoadMoreViewHolder(loadMoreListener, v)
        }else{
            onCreateHolder(parent, viewType)
        }
    }

    abstract fun onBindHolder(holder: Y, position: Int)

    abstract fun onCreateHolder(parent: ViewGroup, viewType: Int): Y

    override fun getItemViewType(position: Int): Int {
        return if (isLoadMore && (position == items.size)){
            -1
        }else{
            super.getItemViewType(position)
        }
    }

    class LoadMoreViewHolder(
        private val listener: LoadMoreListener,
        view: View
    ): BaseViewHolder(view){

        init {
            itemView.i_load_more.setOnClickListener {
                showLoading()
                listener.onLoadMore()
            }

            hideLoading()
        }

        private fun showLoading(){
            itemView.i_progress_load.visibility = View.VISIBLE
            itemView.i_load_more.visibility = View.GONE
        }

        fun hideLoading(){
            itemView.i_progress_load.visibility = View.GONE
            itemView.i_load_more.visibility = View.VISIBLE
        }
    }

    interface LoadMoreListener{
        fun onLoadMore()
    }
}
抽象类BaseAdapter(
private val isLoadMore:Boolean=false
):RecyclerView.Adapter(){
私有变量loadMoreListener=对象:loadMoreListener{
覆盖有趣的onLoadMore(){
onLoad()
}
}
private val listUpdateCallback=对象:listUpdateCallback{
更改后覆盖乐趣(位置:Int,计数:Int,有效负载:Any?){
NotifyItemRange已更改(位置、计数、有效负载)
}
覆盖未插入(位置:Int,计数:Int){
notifyItemRangeInserted(位置、计数)
}
移动时覆盖乐趣(fromPosition:Int,toPosition:Int){
notifyItemMoved(从位置、位置)
}
已移除覆盖(位置:Int,计数:Int){
notifyItemRangeRemoved(位置、计数)
}
}
private val itemDiffCallback=对象:DiffUtil.ItemCallback(){
覆盖内容相同(旧项:T,新项:T):布尔值{
返回this@BaseAdapter.areContentsTheSame(旧项目,新项目)
}
覆盖乐趣项相同(旧项:T,新项:T):布尔值{
返回this@BaseAdapter.areItemsTheSame(旧项目,新项目)
}
}
val data=AsyncListDifference(listUpdateCallback,AsyncDifferConfig.Builder(itemDiffCallback.build())
受保护的抽象趣味内容相同(旧项:T,新项:T):布尔值
受保护的抽象项相同(旧项:T,新项:T):布尔值
打开乐趣更新列表(项目:列表)=数据。提交列表(项目)
open fun updateList(项:列表,回调:Runnable)=data.submitList(项,回调)
重写fun getItemCount():Int=if(isLoadMore&&data.currentList.IsNoteEmpty()){
data.currentList.size+1
}否则{
data.currentList.size
}
private-fun-getActual(index:Int):T?=if(isLoadMore&&(index==items.size-1))null-else项[index]
fun get(index:Int):T=if(isLoadMore&&index==(data.currentList.size)){
data.currentList[索引-1]
}否则{
data.currentList[索引]
}
val items:List get()=data.currentList
打开fun onLoad(){}
@抑制(“未选中的_CAST”)
覆盖BindViewHolder(holder:BaseViewHolder,位置:Int){
if(isLoadMore&(position==items.size)){
(保持架作为LoadMoreViewHolder).hideLoading()
返回
}
ON活页夹(活页夹为Y,位置)
}
重写CreateViewHolder(父级:ViewGroup,viewType:Int):BaseViewHolder{
返回if(viewType==-1){
val v=LayoutInflater.from(parent.context)
.充气(R.layout.item\u load\u more\u loading,父项,错误)
LoadMoreViewHolder(loadMoreListener,v)
}否则{
onCreateHolder(父级,视图类型)
}
}
活页夹(活页夹:Y,位置:Int)
抽象元素onCreateHolder(父对象:ViewGroup,viewType:Int):Y
覆盖getItemViewType(位置:Int):Int{
返回if(isLoadMore&(position==items.size)){
-1
}否则{
super.getItemViewType(位置)
}
}
类LoadMoreViewHolder(
私有val侦听器:LoadMoreListener,
视图:视图
):BaseViewHolder(视图){
初始化{
itemView.i\u load\u more.setOnClickListener{
showLoading()
listener.onLoadMore()
}
hideLoading()
}
私人娱乐节目{
itemView.i\u progress\u load.visibility=View.VISIBLE
itemView.i\u load\u more.visibility=View.GONE
}
趣味阅读{
itemView.i\u progress\u load.visibility=View.GONE
itemView.i\u load\u more.visibility=View.VISIBLE
}
}
接口LoadMoreListener{
乐趣在线下载更多()
}
}
这是我的基本适配器的实现

    class CommentAdapter(
    private val listener: (item: Click)->Unit
): BaseAdapter<Comment, CommentAdapter.Holder>(true){

    override fun areContentsTheSame(oldItem: Comment, newItem: Comment): Boolean {
        return oldItem.id == newItem.id &&
                oldItem.message == newItem.message &&
                oldItem.nicknameName == newItem.nicknameName &&
                oldItem.replyCount == newItem.replyCount &&
                oldItem.stickerImage == newItem.stickerImage &&
                oldItem.createAt == newItem.createAt
    }

    override fun areItemsTheSame(oldItem: Comment, newItem: Comment): Boolean {
        return oldItem.id == newItem.id
    }

    override fun onBindHolder(holder: Holder, position: Int) {
        holder.bind(get(position))
    }

    override fun onCreateHolder(parent: ViewGroup, viewType: Int): Holder {
        val v = LayoutInflater.from(parent.context)
            .inflate(R.layout.item_comment, parent, false)
        return Holder(listener, v)
    }

    override fun onLoad() {
        listener(Click.OnLoadMore)
    }

    class Holder(
        private val listener: (item: Click)->Unit,
        view: View
    ): BaseViewHolder(view){
        private var item: Comment? = null
        private val sharedPreference: ISharedPreference = SharedPreference(itemView.context)

        init {
            itemView.setOnClickListener {
                item?.let {
                    listener(Click.View(it))
                }
            }
        }

        fun bind(item: Comment){
            this.item = item

            Glide.with(itemView.context)
                .load(Media.downloadProfile(item.profileName))
                .into(itemView.item_comment_profile)

            itemView.item_text_nickname.text = item.nicknameName
            itemView.item_text_time.text = DateTime.parse(item.createAt).toString()
            if (sharedPreference.loadFirebaseId() == item.id){
                itemView.item_text_identity.visibility = View.VISIBLE
                itemView.item_text_identity.text = StringBuilder("You")
            }else{
                itemView.item_text_identity.visibility = View.INVISIBLE
            }

            if (item.stickerImage != "" && item.message != ""){
                inflateTextSticker()
            }else if(item.stickerImage != "" && item.message == ""){
                inflateSticker()
            }else if(item.stickerImage == "" && item.message != ""){
                inflateText()
            }

            inflateReply()
        }

        private fun inflateReply(){
            itemView.item_stub_count.layoutResource = R.layout.view_comment_count
            val view = itemView.item_stub_count.inflate()
            view.item_text_reply_count.text = StringBuilder(
                "-------- View ${item!!.replyCount} reply"
            )
            view.item_button_option.setOnClickListener {
                listener(Click.Options(item!!))
            }
        }

        private fun inflateSticker(){
            itemView.item_stub_content.layoutResource = R.layout.view_comment_sticker
            val view = itemView.item_stub_content.inflate()

            Glide.with(itemView.context)
                .load(Media.downloadSticker(item!!.stickerId, item!!.stickerImage))
                .into(view.view_comment_sticker)
        }

        private fun inflateText(){
            itemView.item_stub_content.layoutResource = R.layout.view_comment_text
            val view = itemView.item_stub_content.inflate()

            view.view_text_content.text = item!!.message
        }

        private fun inflateTextSticker(){
            itemView.item_stub_content.layoutResource = R.layout.view_comment_sticker_text
            val view = itemView.item_stub_content.inflate()

            Glide.with(itemView.context)
                .load(Media.downloadSticker(item!!.stickerId, item!!.stickerImage))
                .into(view.view_comment_sticker_sticker)

            view.view_comment_sticker_text_content.text = item!!.message
        }
    }

    sealed class Click{
        class Options(val item: Comment): Click()
        class View(val item: Comment): Click()
        object OnLoadMore: Click()
    }
}
class注释适配器(
专用val侦听器:(项目:单击)->单位
):BaseAdapter(真){
覆盖内容相同(旧项:注释,新项:注释):布尔值{
返回oldItem.id==newItem.id&&
oldItem.message==newItem.message&&
oldItem.昵称名称==newItem.昵称名称&&
oldItem.replyCount==newItem.replyCount&&
oldItem.stickerImage==newItem.stickerImage&&
oldItem.createAt==newItem.createAt
}
覆盖乐趣项相同(旧项:注释,新项:注释):布尔值{
返回oldItem.id==newItem.id
}
覆盖绑定保持架(保持架:保持架,位置:Int){
固定器绑定(获取(位置))
}
重写onCreateHolder(父级:ViewGroup,viewType:Int):Holder{
val v=LayoutInflater.from(parent.context)
.充气(R.layout.item_注释,父项,假)
返回支架(侦听器,v)
}
覆盖乐趣加载(){
侦听器(单击.OnLoadMore)
}
阶级持有者(
专用val侦听器:(项目:单击)->单位,
视图:视图
):BaseViewHolder(视图){
私有变量项:注释?=null
private val sharedPreference:ISharedPreference=sharedPreference(itemView.context)
初始化{
itemView.setOnClickListener{
项目?让我们{
侦听器(单击。查看(it))
}
}
}
趣味绑定(项目:注释){
this.item=项目
Glide.with(itemView.context)
.load(媒体)下载配置文件(项目