当前位置:网站首页>RecycleView懒加载失效问题(二)
RecycleView懒加载失效问题(二)
2022-06-21 18:11:00 【yufumatou】
前言:继《RecycleView懒加载失效问题》之后,再介绍另一个场景,如下图。两层RecycleView,外层是竖向列表样式,内层是网格样式,由于内层网格个数不固定,需要内层RecycleView的根布局高度为wrap_content(注:这是导致内层RecycleView懒加载失效的原因)

问题:尽管第2项只显示了一小部分,但仍加载了全部数据,内层懒加载失效,当内层数据量很大,一次要全部加载,会感觉到卡顿。
分析:首先,分析为什么外层的RecycleView懒加载正常,而内层的RecycleView失效了呢?区别在于外层RecycleView高度是确定的,至少不会超过父控件,而内层根布局高度为wrap_content,即item没有对最大高度做限制,内层需要多大就赋予多大,于是就加载了全部内层的数据,我们可以先将内层的根布局高度设置为固定值验证一下,发现高度固定后内层也支持懒加载了,毕竟RecycleView高度限制了,超过高度的item就不加载了,但是这个就不满足我们的需求了,内层数据少的时候会留白,数据多的时候显示不全,而且只是外层响应滑动事件,内层无法响应,所有我们只能将内层根布局高度设置为wrap_content。
1、外层适配器
class TestPercentAdapter : RecyclerView.Adapter<TestPercentAdapter.TestPercentViewHolder>(){
private val testPercentList = arrayListOf<TestPercentBean>()
init {
for (i in 1..20){
testPercentList.add(TestPercentBean("外层第${i}项"))
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TestPercentViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_test, parent, false)
return TestPercentViewHolder(view)
}
override fun getItemCount(): Int {
return testPercentList.size
}
override fun onBindViewHolder(holder: TestPercentViewHolder, position: Int) {
holder.tvItem.text = testPercentList[position].mTitle
holder.adapterTwo.testChildrenList = testPercentList[position].mChildrenList
holder.adapterTwo.notifyDataSetChanged()
Log.e("aa", "***************${testPercentList[position].mTitle}")
}
inner class TestPercentViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val tvItem = view.findViewById<TextView>(R.id.tv_item)
val rvItem = view.findViewById<RecyclerView>(R.id.rv_item)
val adapterTwo = TestChildrenAdapter()
init {
rvItem.layoutManager = GridLayoutManager(rvItem.context, 2)
rvItem.adapter = adapterTwo
}
}
}2、外层布局
<?xml version="1.0" encoding="utf-8"?>
<com.hualala.myapplication.MyLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_item"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:textColor="@color/colorAccent"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.hualala.myapplication.MyLinearLayout>3、内层适配器
class TestChildrenAdapter : RecyclerView.Adapter<TestChildrenAdapter.TestChildrenViewHolder>(){
var testChildrenList = arrayListOf<TestPercentBean.TestChildrenBean>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TestChildrenViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_test_two, parent, false)
return TestChildrenViewHolder(view)
}
override fun getItemCount(): Int {
return testChildrenList.size
}
override fun onBindViewHolder(holder: TestChildrenViewHolder, position: Int) {
holder.tv_test.text = testChildrenList[position].mTitle
Log.e("aa", "***********${testChildrenList[position].mTitle}")
}
class TestChildrenViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tv_test = itemView.findViewById<TextView>(R.id.tv_test)
}
}4、内层布局
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv_test"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:textColor="@color/colorPrimaryDark"/>5、主页布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rv_test"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintWidth_percent="0.5"/>
<View
android:layout_width="1px"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="#666666"/>
<Button
android:id="@+id/bt_update"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@+id/rv_test"
android:layout_marginStart="10dp"
android:layout_marginRight="10dp"
app:layout_constraintEnd_toEndOf="parent"
android:gravity="center"
android:text="更新"/>
</androidx.constraintlayout.widget.ConstraintLayout>6、加载数据
rv_test.layoutManager = LinearLayoutManager(this)
rv_test.adapter = TestPercentAdapter()
bt_update.setOnClickListener { (rv_test.adapter as TestPercentAdapter).notifyDataSetChanged() }8、实体类
class TestPercentBean constructor(title: String){
val mTitle = title
val mChildrenList = ArrayList<TestChildrenBean>()
init {
for (i in 1..(Math.random() * 100).toInt()){
mChildrenList.add(TestChildrenBean("内层第{$i}项"))
}
}
class TestChildrenBean constructor(title: String){
val mTitle = title
}
}方案:分析了原因,有了初步的方案,需要满足这两个条件即可解决:1、给内部RecycleView设置最大高度为外层RecycleView高度(解决懒加载,最多加载条数进行了限制,不会无限大) 2、滑动冲突(这部分太过于复杂,导致最终放弃了该方案,可以想一下我点击在第一项内层的RecycleView上向上滑动,由于已经都显示了无需再加载了需要把事件交给外层RecycleView,但当第2项内层RecycleView全部显示出来时,又要将事件给第2项内层RecycleView继续加载剩下的数据,全部显示后再将事件交给外层RecycleView——即内层RecycleView布局未全部显示出来时外层响应滑动,全部显示则内层响应,如果内层滑动到第1item或最后item,则再由外层响应)
简单方案:考虑上面的方案复杂,那就换一种思路,用单层RecycleView实现,则需要网格支持动态分配列数,当为外层数据时为1列,为内层数据时为2列。
通过GridLayoutManager.SpanSizeLookup实现动态列数
1、GridLayoutManager第2个参数spanCount为每行列数的最小公倍数
2、getSpanSize返回值为spanCount除以该行列数
1、适配器
class TestAdapter : RecyclerView.Adapter<TestAdapter.TestViewHolder>() {
var testList = ArrayList<TestBean>()
init {
for (i in 1..20) {
testList.add(TestBean("外层第${i}项", true))
for (j in 1..(Math.random() * 100).toInt()) {
testList.add(TestBean("内层第${j}项", false))
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TestViewHolder {
val view =
LayoutInflater.from(parent.context).inflate(R.layout.item_test_two, parent, false)
return TestViewHolder(view)
}
override fun getItemCount(): Int {
return testList.size
}
override fun onBindViewHolder(holder: TestViewHolder, position: Int) {
holder.tv_test.text = testList[position].mTitle
if (testList[position].mIsPercent){
holder.tv_test.setTextColor(holder.tv_test.resources.getColor(R.color.colorAccent))
}else{
holder.tv_test.setTextColor(holder.tv_test.resources.getColor(R.color.colorPrimaryDark))
}
Log.e("aa", "***********${testList[position].mTitle}")
}
class TestViewHolder constructor(view: View) : RecyclerView.ViewHolder(view) {
val tv_test = itemView.findViewById<TextView>(R.id.tv_test)
}
}2、子项布局
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/tv_test"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:textColor="@color/colorPrimaryDark"/>3、实体类
class TestBean(title: String, isPercent: Boolean) {
val mTitle = title
val mIsPercent = isPercent
}4、加载数据
/* 1、GridLayoutManager第2个参数spanCount为每行列数的最小公倍数
* 2、getSpanSize返回值为spanCount除以该行列数
* */
val gridLayoutManager = GridLayoutManager(this, 2)
val testAdapter = TestAdapter()
gridLayoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup(){
override fun getSpanSize(position: Int): Int {
return if (testAdapter.testList[position].mIsPercent) 2 else 1
}
}
rv_test.layoutManager = gridLayoutManager
rv_test.adapter = testAdapter
bt_update.setOnClickListener { (rv_test.adapter as TestAdapter).notifyDataSetChanged() }
边栏推荐
- 三叶的小伙伴们の经历分享 : 千秋澪(千秋总)
- 力扣今日题1108. IP 地址无效化
- Shang Silicon Valley Shang Silicon Valley | what is Clickhouse table engine memory and merge
- How to create network redundancy for network managed national production reinforced switch
- 2022年6月25日PMP考试通关宝典-4
- 记一些PAT题目(一)
- 如何使用DevExpress WPF在WinUI中创建第一个MVVM应用?
- How to temporarily modify samesite=none and secure in Chrome browser
- 动态规划【二】(线性dp)
- 力扣每日一练之双指针1Day8
猜你喜欢

Nepal graph has settled in Alibaba cloud computing nest to help enterprises build a super large-scale map database on the cloud

vivo 容器集群监控系统架构与实践

Huawei launches new products again? These models have excellent functions

Kubernetes 跨 StorageClass 迁移 Persistent Volumes 完全指南

jvm造轮子

Tableapi & SQL and example module of Flink

508. Most Frequent Subtree Sum

Startup mode of Jupiter notebook and related problems

Whether Gorm database needs to set foreign keys

Medical expense list can be entered at a second speed, and OCR recognition can help double the efficiency
随机推荐
如何在Chrome浏览器中模拟请求或修改请求的域名
婴儿名字[连通分量之邻接矩阵与DFS]
Hongmeng version of "Tiktok" is a great experience
CPDA|数据分析师需要具备哪些基本功?
R语言使用plyr包的rbind.fill函数纵向合并两个数据列不同的dataframe数据
Excel文件加密的两种方式
An accident caused by a MySQL misoperation, and the "high availability" cannot withstand it!
CloudCompare&PCL 根据匹配点计算变换矩阵
Medical expense list can be entered at a second speed, and OCR recognition can help double the efficiency
Codeforces Round #394 (Div. 2) E. Dasha and Puzzle
mocklog_模拟日志
EasyCVR智能边缘网关硬件如何设置通电自启动?
Must the database primary key be self incremented? What scenarios do not suggest self augmentation?
Summary of the 13th week
C. Helping the Nature(cf)差分
Flink 系例 之 TableAPI & SQL 与 示例模块
The R language uses the follow up The plot function visualizes the longitudinal follow-up chart of multiple ID (case) monitoring indicators, and uses line Col parameter custom curve color (color)
文件上传漏洞靶场分析 UPLOAD_LABS
The dist function of R language calculates the distance between two samples in dataframe data and returns the distance matrix between samples. The distance matrix is input to the hclust function for h
论文解读(USIB)《Towards Explanation for Unsupervised Graph-Level Representation Learning》