当前位置:网站首页>Recycleview lazy load failure (II)

Recycleview lazy load failure (II)

2022-06-21 19:58:00 yufumatou

Preface : Following 《RecycleView Lazy load failure 》 after , Let's introduce another scenario , Here's the picture . Two layers of RecycleView, The outer layer is a vertical list style , The inner layer is grid style , Because the number of inner grids is not fixed , Inner layer required RecycleView The root layout height of is wrap_content( notes : This is what causes the inner layer RecycleView Causes of lazy loading failure

problem : Even though the 2 The item shows only a small part , But all the data is still loaded , Inner lazy loading failure , When there is a large amount of internal data , Load all at once , I'll feel carton .

analysis : First , Analyze why the outer layer RecycleView Lazy loading normal , And the inner RecycleView Failed ? The difference is that the outer layer RecycleView The height is certain , At least not more than the parent control , The inner root layout height is wrap_content, namely item There is no limit on the maximum height , As big as the inner layer needs to be , So all the inner data is loaded , We can first set the root layout height of the inner layer to a fixed value to verify , It is found that the inner layer also supports lazy loading after the height is fixed , After all RecycleView Height limits , Exceeding the height of item It doesn't load , But this does not meet our needs , When there is little internal data, it will be left blank , The display is incomplete when there is too much data , And only the outer layer responds to sliding Events , The inner layer cannot respond , So we can only set the inner root layout height to wrap_content.

1、 Outer adapter

class TestPercentAdapter : RecyclerView.Adapter<TestPercentAdapter.TestPercentViewHolder>(){
    private val testPercentList = arrayListOf<TestPercentBean>()

    init {
        for (i in 1..20){
            testPercentList.add(TestPercentBean(" Outer layer ${i} term "))
        }
    }

    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、 Outer layout

<?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、 Inner adapter

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、 Interior layout

<?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、 Home page layout

<?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=" to update "/>
</androidx.constraintlayout.widget.ConstraintLayout>

6、 Load data

rv_test.layoutManager = LinearLayoutManager(this)
        rv_test.adapter = TestPercentAdapter()
        bt_update.setOnClickListener { (rv_test.adapter as TestPercentAdapter).notifyDataSetChanged() }

8、 Entity class

class TestPercentBean constructor(title: String){
    val mTitle = title
    val mChildrenList = ArrayList<TestChildrenBean>()
    init {
        for (i in 1..(Math.random() * 100).toInt()){
            mChildrenList.add(TestChildrenBean(" Inner layer {$i} term "))
        }
    }
    
    class TestChildrenBean constructor(title: String){
        val mTitle = title
    }
}

programme : The reason is analyzed , We have a preliminary plan , These two conditions need to be met to solve :1、 To the interior RecycleView Set the maximum height to outer layer RecycleView Height ( Solve lazy loading , The maximum number of loaded pieces is limited , Not infinite ) 2、 Slide conflict ( This part is too complicated , This led to the eventual abandonment of the scheme , Think about what I clicked on in the first item RecycleView Slide up and up , Since it has been shown that there is no need to load any more, the event needs to be handed over to the outer layer RecycleView, But Dangdi 2 Intranuchal layer RecycleView When all are displayed , And send the event to the 2 Intranuchal layer RecycleView Continue loading the remaining data , After all are displayed, the event is handed over to the outer layer RecycleView—— Inner layer RecycleView The outer layer responds to sliding when the layout is not fully displayed , If all are displayed, the inner layer will respond , If the inner layer slides to the 1item Or last item, Then the outer layer will respond

Simple plan : Consider the complexity of the above scheme , Then change your mind , With single layer RecycleView Realization , You need the grid to support dynamic allocation of columns , When it is outer data, it is 1 Column , For inner layer data, it is 2 Column .

adopt GridLayoutManager.SpanSizeLookup Realize the dynamic number of columns

1、GridLayoutManager The first 2 Parameters spanCount Is the least common multiple of the number of rows and columns 
2、getSpanSize The return value is spanCount Divide by the number of rows 

1、 Adapter

class TestAdapter : RecyclerView.Adapter<TestAdapter.TestViewHolder>() {

    var testList = ArrayList<TestBean>()

    init {
        for (i in 1..20) {
            testList.add(TestBean(" Outer layer ${i} term ", true))
            for (j in 1..(Math.random() * 100).toInt()) {
                testList.add(TestBean(" Inner layer ${j} term ", 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、 Item layout

<?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、 Entity class

class TestBean(title: String, isPercent: Boolean) {
    val mTitle = title
    val mIsPercent = isPercent
}

4、 Load data

/* 1、GridLayoutManager The first 2 Parameters spanCount Is the least common multiple of the number of rows and columns 
 * 2、getSpanSize The return value is spanCount Divide by the number of rows 
 * */
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() }

 

原网站

版权声明
本文为[yufumatou]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/172/202206211811197923.html