前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android BaseQuickAdapter3.0.4版本二级列表的使用及遇到的问题

Android BaseQuickAdapter3.0.4版本二级列表的使用及遇到的问题

作者头像
Vaccae
发布2021-11-17 10:41:35
2.1K0
发布2021-11-17 10:41:35
举报
文章被收录于专栏:微卡智享微卡智享

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为3942,预计阅读9分钟

前言

前阵子做的新产品用使用BaseQuickAdapter中的basemultiitemquickadapter来实现二级列表,网的这个相关的资料也挺多,使用的版本是2.9.4,在使用中发现当二级列表展开时对子列表数据进行操作后,列表中展开和闭合显示的数据会异常。因为当时项目比较急,3.0版本的用法和原来完全不一样了,加上这个问题不大,所以就没再处理,现在抽出空来就想试试3.0版本的实现方式,毕竟作者说3.0使用kotlin重写了不少,并解决了一些2.0版本中的BUG。

实现效果

‍上图中可以看出,在展开列表中做删除明细的操作后,数据显示的就异常了,这个是在2.X的版本中出现的问题,现在3.0里面还是有这个情况。

不过这个倒不是本篇的重点,实际用到的这个场景应该比较少,本篇主要是说一下3.0版本中多级列表的实现方式,另外这个Demo中也是初次尝试MutableSharedFlow的来替代LiveData,使用中有些还没理解明白,管他叫经,先用了再说。

代码实现

微卡智享

在2.x版本中,使用多级列表用的BaseMultiItemQuickAdapter,定义的类要继承自MultiItemEntity,现在3.0版本中,我使用的是BaseNodeAdapter,定义的类也是继承自BaseNode和BaseExpandNode。

01

Demo总览

build.gradle中加入引用项

代码语言:javascript
复制
    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'

    //使用协程
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
    
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'

02

类的定义

Body子列表继承自BaseNode,因为是最末级了,所以childNode设置为NULL

代码语言:javascript
复制
class Body : BaseNode() {

    var code: String = ""
    var name: String = ""
    var specs: String = ""
    var batchno: String = ""
    var qty: Int = 0

    override val childNode: MutableList<BaseNode>?
        get() = null
}

Head父级列表继承自BaseExpandNode,其中要定义其明细列表MutableList<BaseNode>

代码语言:javascript
复制
class Head : BaseExpandNode() {

    var Bodys: MutableList<BaseNode>? = null

    var deptno: String = ""
    var deptname: String = ""

    override val childNode: MutableList<BaseNode>?
        get() = Bodys
}

03

adapter适配器

DataAdatper适配器继承自BaseNodeAdapter,使用NodeProvider将一级列表Head和二级列表Body分开写,代码看起来也方便些。

代码语言:javascript
复制
class DataAdapter : BaseNodeAdapter {

    constructor() : super() {
        addNodeProvider(HeadProvider())
        addNodeProvider(BodyProvider())
    }

    override fun getItemType(data: List<BaseNode>, position: Int): Int {
        val node = data[position]
        if (node is Head) {
            return 1
        } else if(node is Body){
            return 2
        }
        return -1;
    }
    
}

HeadProvider

代码语言:javascript
复制
class HeadProvider : BaseNodeProvider() {

    override val itemViewType: Int
        get() = 1

    override val layoutId: Int
        get() = R.layout.rcl_head

    override fun convert(helper: BaseViewHolder, item: BaseNode) {
        val head = item as Head
        helper.setText(R.id.tv_deptno, head.deptno)
            .setText(R.id.tv_deptname, head.deptname)
    }

    override fun onClick(helper: BaseViewHolder, view: View, data: BaseNode, position: Int) {
        super.onClick(helper, view, data, position)

        // 这里使用payload进行增量刷新(避免整个item刷新导致的闪烁,不自然)
        getAdapter()!!.expandOrCollapse(
            position,
            true,
            true,
            110
        )
    }
}

BodyProvider

代码语言:javascript
复制
class BodyProvider: BaseNodeProvider() {

    override val itemViewType: Int
        get() = 2
    override val layoutId: Int
        get() = R.layout.rcl_body

    override fun convert(helper: BaseViewHolder, item: BaseNode) {
        val body = item as Body
        helper.setText(R.id.tv_code, body.code)
            .setText(R.id.tv_name, body.name)
            .setText(R.id.tv_specs, body.specs)
            .setText(R.id.tv_qty, "${body.qty}")
    }
}

04

ViewModel中使用Flow

ViewModel类中定义了MutableSharedFlow

更新MutableSharedFlow的数据时,使用了tryEmit方式

加入了初始化生成数据,插入一条数据和删除一条数据的三个方法,完整的ViewModel代码

代码语言:javascript
复制
class DataViewModel: ViewModel() {

    val DataList = MutableSharedFlow<MutableList<BaseNode>>(
        replay = 1,
        onBufferOverflow = BufferOverflow.DROP_OLDEST
    )

    fun InitDataList() {
        val headlist = ArrayList<BaseNode>()
        for (i in 1..3) {
            val tmphead = Head()
            tmphead.deptno = "000$i"
            tmphead.deptname = "部门$i"
            tmphead.Bodys = mutableListOf()

            for (k in 1..5) {
                val tmpbody = Body()
                tmpbody.code = "1000$k"
                tmpbody.name = "产品$k"
                tmpbody.batchno = "20231101-$k"
                tmpbody.specs = "20ml"
                tmpbody.qty = i * k

                tmphead.Bodys?.add(tmpbody)
            }

            tmphead.isExpanded = false
            headlist.add(tmphead)
        }

        DataList.tryEmit(headlist);
    }


    fun AddBody(num:Int) {
        val headlist = DataList.replayCache.first()
        if (headlist.size > 0) {
            val head = headlist.get(0)
            val tmpbody = Body()
            tmpbody.code = "1000$num"
            tmpbody.name = "新建产品$num"
            tmpbody.batchno = "20231101-$num"
            tmpbody.specs = "20ml"
            tmpbody.qty = num

            head.childNode?.add(tmpbody)
        }
        DataList.tryEmit(headlist);
    }

    fun DelBody() {
        val headlist = DataList.replayCache.first()
        if (headlist.size > 0) {
            val head = headlist.get(0)
            head.childNode?.let {
                if (it.size > 0) {
                    it.removeAt(0)
                }
            }
        }
        DataList.tryEmit(headlist);
    }
}

05

Activity中监听刷新数据

在Activity中先定义LifecycleCoroutineScope

监听Flow的数据改变,需要在onStart中实现,在onStop中还有停止监听

其实像我这么简单的数据来说,感觉还是用LiveData更方便,而且使用起来也更简单。

完整的Activity代码

代码语言:javascript
复制
class MainActivity : AppCompatActivity() {

    private val btn1:Button by lazy { findViewById(R.id.btn1) }
    private val btn2:Button by lazy { findViewById(R.id.btn2) }
    private val recyclerView:RecyclerView by lazy { findViewById(R.id.recycler_view) }

    private var lifecyclejob : LifecycleCoroutineScope? = null;

    private lateinit var viewModel: DataViewModel
    private lateinit var adapter: DataAdapter


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        lifecyclejob = lifecycleScope

        viewModel = DataViewModel()

        viewModel.InitDataList()
        adapter = DataAdapter()

        adapter.setList(viewModel.DataList.replayCache.first())

        recyclerView.layoutManager = LinearLayoutManager(this)
        recyclerView.adapter = adapter

        btn1.setOnClickListener {
            viewModel.AddBody(10)
        }

        btn2.setOnClickListener {
            viewModel.DelBody()
        }
    }

    override fun onStart() {
        super.onStart()

        lifecyclejob?.let {
            it.launch {
                viewModel.DataList
                    .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
                    .collect {
                        adapter.setDiffNewData(it)
                    }
            }
        }

    }

    override fun onStop() {
        lifecyclejob?.let {
            it.cancel()
        }
        super.onStop()

    }
}

TIPS

这两天也是抽空在做Android使用OpenCV4.5.4的人脸识别功能,开始还想做个简单的Demo,结果现在越做感觉越有点麻烦,还要再花些时间了,等完成会第一时间更新。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微卡智享 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
人脸识别
腾讯云神图·人脸识别(Face Recognition)基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、比对、搜索、验证、五官定位、活体检测等多种功能,为开发者和企业提供高性能高可用的人脸识别服务。 可应用于在线娱乐、在线身份认证等多种应用场景,充分满足各行业客户的人脸属性识别及用户身份确认等需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档