我有Recyler视图显示每页5个项目。但我不想无休止的滚动或自动加载。但是我想显示加载更多按钮列表的末尾,当用户单击该“加载更多”按钮将加载下一个数据。我已经成功表明了这一点。但是问题是当加载更多时,单击按钮加载更多的混乱。并将第一页的最后一项复制到第二页。
这是我的RecycleViewAdapter
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()
}
}
这是我的基本适配器工具
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()
}
}