【Android】BaseQuickAdapter使用(RecyclerView万能适配器)

05-14 1006阅读

目录

  • 前言
  • 一、导入依赖
  • 二、适配器比较
  • 三、基础使用
  • 四、多布局和分组布局
    • 1.BaseMultiItemQuickAdapter
    • 2.BaseDelegateMultiAdapter
    • 3.BaseProviderMultiAdapter
    • 4.BaseSectionQuickAdapter
    • 总结

      前言

      RecyclerView是Android用于取代ListView的SDK,它的灵活性和可替代性都比ListView更好,但RecyclerView也存在一些问题: 高度不能自适应、最后一个 Item 显示不全被遮挡等。而无论ListView还是RecyclerView都必不可少地会使用到适配器,其配置比较繁琐。

      【Android】BaseQuickAdapter使用(RecyclerView万能适配器)
      (图片来源网络,侵删)

      BaseQuickAdapter 可以对繁琐的适配器进行快速构建,相比原始的RecyclerView.Adapter适配器,能减少70%以上的代码。

      本文将使用Kotlin语言来编写,Kotlin作为安卓板块的新语言,集大家之所长,一定程度上提高了开发效率,后续会有介绍。


      BRVAH官方使用指南:BRVAH官方使用指南


      一、导入依赖

      在 build.gradle(Module:app) 的 dependencies 添加:

      dependencies {
      	implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'
      }
      

      二、适配器比较

      1. 原始的 RecyclerView.Adapter:
      class RecyclerAdapter(private val context: Context, private val data: List)
          : RecyclerView.Adapter() {
          
          override fun getItemCount(): Int = data.size
          
          override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder?{
              return MyRecyclerViewHolder(LayoutInflater.from(context)
                          .inflate(R.layout.item_recycler, parent, false))
          }
          //override fun getItemViewType(position: Int): Int{}
          override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
              holder.textView.text = ""
              holder.textView.setOnClickListener {}
          }
          inner class MyRecyclerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
              var textView: TextView = view.findViewById(R.id.item_tv)
          }
      }
      

      原始的 RecyclerView.Adapter 需要编写4~5个方法:

      1、getItemCount

      2、onCreateViewHolder

      3、getItemViewType

      4、onBindViewHolder

      5、MyRecyclerViewHolder自定义ViewHolder

      1. BaseQuickAdapter适配器:
      class MyAdapter(private val layoutRes: Int) :
          BaseQuickAdapter(layoutRes) {
          override fun convert(holder: BaseViewHolder, item: String) {
              holder.setText(R.id.textView, item)
          }
      }
      

      只需要继承BaseQuickAdapter,第一个泛型对应数据类型ItemBean,第二个泛型对应ViewHolder,一般直接填写BaseViewHolder。

      然后在convert方法(类似onBindViewHolder方法)中绑定数据、设置事件等,这样只需要编写一个方法即可完成大量的适配工作。

      三、基础使用

      1. 添加到 RecycleView
      	val layoutManager = LinearLayoutManager(this)
      	recyclerView.layoutManager = layoutManager
      	val adapter=MyAdapter(R.layout.item_recycler)
      	recyclerView.adapter = adapter
      
      1. 赋值并刷新
      	adapter.setNewInstance(data) //或者setNewData(),初始化数据
      	adapter.setList(data) //更新数据
      
      1. holder常用方法
      	holder.getView(viewId) //获取控件
      	holder.setText(R.id.textView, str) //设置文本
      	holder.getView(viewId).setOnClickListener {} //指定控件的点击事件
      	holder.getLayoutPosition() //获取当前item的position
      
      1. 外部添加点击事件
      	//item整体点击事件
          adapter.setOnItemClickListener { adapter, view, position ->
              onItemClick(view,position)
          }
          //注册item对应子控件
      	adapter.addChildClickViewIds(R.id.item_tv) 
          //item子控件点击事件
          adapter.setOnItemChildClickListener { adapter, view, position ->
              onItemChildClick(view,position)
          }
      
      1. 添加动画
      	adapter.setAnimationWithDefault(type)
      	//默认的AnimationType类型:AlphaIn, ScaleIn, SlideInBottom, SlideInLeft, SlideInRight
      
      1. 添加头部、尾部、空布局
      	//添加头部、尾部、空布局
          val footView: View =
              LayoutInflater.from(this).inflate(R.layout.layout_foot, recyclerView, false)
          adapter.setFooterView(footView)
          val headView: View =
              LayoutInflater.from(this).inflate(R.layout.layout_head, recyclerView, false)
          adapter.setHeaderView(headView)
          val emptyView: View =
              LayoutInflater.from(this).inflate(R.layout.layout_empty, recyclerView, false)
          adapter.setEmptyView(emptyView)
      
      1. 刷新加载相关
      	//打开或关闭上拉加载
      	adapter.setEnableLoadMore(boolean)
      	// 滑动最后一个Item的时候回调onLoadMoreRequested方法
      	adapter.setOnLoadMoreListener(requestLoadMoreListener)
      	//加载完成
      	adapter.loadMoreComplete();
      	//加载失败
      	adapter.loadMoreFail();
      	//加载结束
      	adapter.loadMoreEnd();
      	//设置自定义加载布局
      	adapter.setLoadMoreView(CustomLoadMoreView())
      	//如果上拉结束后,下拉刷新需要再次开启上拉监听,需要使用setNewData方法填充数据
      	//--------------------
      	
      	//打开或关闭下拉刷新
      	adapter.setUpFetchEnable(true)
      	//设置刷新监听
      	adapter.setUpFetchListener(BaseQuickAdapter.UpFetchListener(){})
      	//设置开始加载的位置
      	adapter.setStartUpFetchPosition(2)
      
      1. 添加拖拽、滑动删除
      	val adapter = ItemDragAdapter(mData) // adapter 需要继承 BaseItemDraggableAdapter
      	val itemDragAndSwipeCallback = ItemDragAndSwipeCallback(adapter) //拖拽和删除回调
      	val itemTouchHelper = ItemTouchHelper(itemDragAndSwipeCallback) 
      	itemTouchHelper.attachToRecyclerView(recyclerView)  //绑定 recycleView
      	
      	// 开启拖拽
      	adapter.enableDragItem(itemTouchHelper, R.id.item_tv, true)
      	adapter.setOnItemDragListener(onItemDragListener) //实现 OnItemDragListener 接口
      	
      	// 开启滑动删除
      	adapter.enableSwipeItem()
      	adapter.setOnItemSwipeListener(onItemSwipeListener) //实现 OnItemSwipeListener 接口
      

      -------------------修订内容:2023-5-15 ----------------------

      最新版本已经找不到 BaseItemDraggableAdapter 类了,不知道为什么。

      解决办法:第二和第三种后续会在我的博客更新如何使用,配置都比较简单的,百度也能找到

      第一种办法:将版本号换成:2.9.30,但是 3.0.4 和 2.9.30 部分类包位置有改动,而且使用写法也有不同,若以前使用过,换版本的话需要对以前的代码全部进行修改

      第二种办法:手动实现 RecyclerView 的 ItemTouchHelper 的回调

      第三种办法:只是实现侧滑功能,可以使用第三方包:com.mcxtzhang.swipemenulib.SwipeMenuLayout

      四、多布局和分组布局

      • 分组布局继承类:

        BaseSectionQuickAdapter:快速实现带头部的适配器

        • 多布局继承类:根据需求选择

          BaseMultiItemQuickAdapter:适用于类型较少,业务不复杂的场景,便于快速使用

          BaseDelegateMultiAdapter:数据类型任意,代理类方式,适用于实体类不方便拓展

          BaseProviderMultiAdapter:数据类型任意,不限定ViewHolder类型,单独的自定义ViewHolder类,避免在convert方法中做大量的业务逻辑

          1.BaseMultiItemQuickAdapter

          数据类必须实现MultiItemEntity接口,需要给每一个数据设置itemType。

          class BaseMultiQuickItem(override val itemType: Int, val data: BaseQuickerItem) : MultiItemEntity {
               companion object {
                    const val FIRST_TYPE = 1
                    const val SECOND_TYPE = 2
               }
          }
          

          适配器重写getItemType方法来返回不同的数据类型。

          inner class BaseQuickInfoListAdapter :
          	 BaseMultiItemQuickAdapter() {
          	 
          	 init {
          	     addItemType(BaseMultiQuickItem.FIRST_TYPE, R.layout.layout_first_item)
          	     addItemType(BaseMultiQuickItem.SECOND_TYPE , R.layout.layout_second_item)
          	 }
          	
          	 override fun convert(holder: BaseViewHolder, itemMulti: BaseMultiQuickItem) {
          	     when(holder.itemViewType){
          	         BaseMultiQuickItem.FIRST_TYPE  -> {
          	             holder.setText(R.id.item_tv, "布局一")
          	         }
          	         BaseMultiQuickItem.SECOND_TYPE  -> {
          	             holder.setText(R.id.item_tv, "布局二")
          	         }
          	     }
          	 }
          	}
          

          2.BaseDelegateMultiAdapter

          使用代理类的方式,返回布局id和item类型,数据类依然使用 BaseMultiQuickItem。

          class DelegateMultiAdapter :
          	BaseDelegateMultiAdapter() {
          	override fun convert(helper: BaseViewHolder, item: BaseMultiQuickItem?) {
          	    when (helper.itemViewType) {
          	        BaseMultiQuickItem.FIRST_TYPE -> helper.setText(R.id.item_tv,"布局一")
          	        BaseMultiQuickItem.SECOND_TYPE -> {
          	            when (helper.layoutPosition % 2) {
          	                0 -> helper.setText(R.id.item_tv, "布局二 第一种")
          	                1 -> helper.setText(R.id.item_tv, "布局二 第二种")
          	                else -> {}
          	            }
          	        }
          	        else -> {}
          	    }
          	}
          	
          	init {
          	    //设置代理,通过内部类返回类型
          	    setMultiTypeDelegate(object : BaseMultiTypeDelegate() {
          	        override fun getItemType(data: List, position: Int):Int {
          	            when (position % 3) {
          	                0 -> return BaseMultiQuickItem.FIRST_TYPE
          	                1 -> return BaseMultiQuickItem.SECOND_TYPE
          	                else -> {}
          	            }
          	            return 0
          	        }
          	    })
          	    //将类型和布局绑定
          	    getMultiTypeDelegate()
          	        ?.addItemType(BaseMultiQuickItem.FIRST_TYPE, R.layout.layout_base_quick_first_item)
          	        ?.addItemType(BaseMultiQuickItem.SECOND_TYPE, R.layout.layout_base_quick_second_item)
          	}
          }
          

          3.BaseProviderMultiAdapter

          当有多种条目时,避免在convert方法中做大量的业务逻辑,将每种Item都分离成一个个单独的类,然后整合到适配器中,最大化自定义数据类型。

          class ProviderMultiAdapter : BaseProviderMultiAdapter() {
          	override fun getItemType(data: List, position: Int): Int {
          	    when (position % 3) {
          	        0 -> return BaseMultiQuickItem.FIRST_TYPE
          	        1 -> return BaseMultiQuickItem.SECOND_TYPE
          	        else -> {}
          	    }
          	    return 0
          	}
          	
          	init {
          	    // 注册 Provider
          	    addItemProvider(FirstItemProvider())
          	    addItemProvider(SecondItemProvider())
          	}
          	}
          

          把大量的业务逻辑抽取到了对应的ItemProvider中。

          class FirstItemProvider : BaseItemProvider() {
              override val itemViewType: Int
                  get() = BaseMultiQuickItem.FIRST_TYPE
              override val layoutId: Int
                  get() = R.layout.layout_first_item
              //可返回自定义的 ViewHolder
              override fun onCreateViewHolder(parent: ViewGroup, viewType:Int): BaseViewHolder {
                  return super.onCreateViewHolder(parent,viewType)
              }
              override fun convert(helper: BaseViewHolder, data: BaseMultiQuickItem?) {
                  if (helper.absoluteAdapterPosition % 2 === 0) {
                      helper.setText(R.id.item_tv, "")
                  } else {
                      helper.setText(R.id.item_tv, "")
                  }
              }
              override fun onClick(
                  helper: BaseViewHolder,
                  view: View,
                  data: BaseMultiQuickItem?,
                  position: Int
              ) {}
          }
          

          4.BaseSectionQuickAdapter

          数据类需继承SectionEntity抽象类。

          class BaseSectionQuickItem(
               override val isHeader: Boolean, 
               bean: BaseQuickerItem
          ) : SectionEntity()
          

          适配器:

          class SectionQuickAdapter(layoutResId: Int, sectionHeadResId: Int, data: MutableList?) :
          	BaseSectionQuickAdapter(layoutResId, sectionHeadResId, data) {
          	override fun convert(helper: BaseViewHolder, item: BaseSectionQuickItem) {
          	}
          	
          	override fun convertHeader(helper: BaseViewHolder, item: BaseSectionQuickItem) {
          	}
          }
          

          总结

          BaseQuickAdapter功能强大,可以实现多布局、上拉刷新、下拉加载、侧滑删除、甚至树状列表等功能,且方便快捷,如果想要提高开发效率,适配器优先推荐使用它。这里可能介绍不全,详细的可参考官方文档。

          五一假期的第一天,被迫码字和学习😭

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]