子回收器视图的预取视图不起作用

Prefetching view for child recycler view is not working

我有垂直 RecyclerView 和子(嵌套)水平 RecyclerView。 对于第二个回收器,我使用布局管理器:

LinearLayoutManager(itemView.context, LinearLayoutManager.HORIZONTAL, false).apply {
                    isItemPrefetchEnabled = true
                    initialPrefetchItemCount = 4
                }

但嵌套回收器只构建前两个可见项。

完整代码:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val recycler = findViewById<RecyclerView>(R.id.recycler)

        recycler.layoutManager = LinearLayoutManager(this)
        recycler.adapter = MainAdapter(buildElements())
    }

    private fun buildElements(): List<Parent> {
        return (0..2).map { pCount -> createParent(pCount) }
    }

    private fun createParent(index: Int): Parent {
        return Parent(text = "$index",
            list = (0..30).map { Child("item $it") }
        )
    }
}

主适配器

class MainAdapter(private val list: List<Parent>) : RecyclerView.Adapter<MainAdapter.CustomHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomHolder {
        val inflater = LayoutInflater.from(parent.context)
        return CustomHolder(inflater.inflate(R.layout.item, parent, false))
    }

    override fun getItemCount(): Int = list.size

    override fun onBindViewHolder(holder: CustomHolder, position: Int) {
        holder.bind(list[position])
    }

    class CustomHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val recycler = itemView.findViewById<RecyclerView>(R.id.recyclerView)
        private val title = itemView.findViewById<TextView>(R.id.title)

        init {
            recycler.layoutManager =
                LinearLayoutManager(itemView.context, LinearLayoutManager.HORIZONTAL, false).apply {
                    isItemPrefetchEnabled = true
                    initialPrefetchItemCount = 4
                }
        }

        fun bind(data: Parent) {
            title.text = data.text
            recycler.adapter = ChildAdapter(data.list)
        }
    }
}

主要回收元素

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="match_parent"
             android:layout_height="wrap_content">

    <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="16dp"/>

    <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_marginTop="16dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
</FrameLayout>

子适配器

class ChildAdapter(private val list: List<Child>) : RecyclerView.Adapter<ChildAdapter.ChildHolder>() {

    companion object {
        private val TAG = ChildAdapter::class.java.simpleName
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChildHolder {
        val inflater = LayoutInflater.from(parent.context)
        return ChildHolder(inflater.inflate(R.layout.child, parent, false))
    }

    override fun getItemCount(): Int = list.size

    override fun onBindViewHolder(holder: ChildHolder, position: Int) {
        holder.bind(list[position])
    }

    class ChildHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val title = itemView.findViewById<TextView>(R.id.childText)
        fun bind(data: Child) {
            title.text = data.text
            Log.d(TAG, "bind child element: ${data.text}")
        }
    }
}

和子元素:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="275dp"
        android:padding="8dp"
        android:layout_height="100dp">

    <TextView
            android:id="@+id/childText"
            android:layout_width="wrap_content"
            android:layout_gravity="center"
            android:layout_height="wrap_content"/>
</FrameLayout>

在日志中只能看到这个:

D/ChildAdapter: bind child element: item 0
D/ChildAdapter: bind child element: item 1
D/ChildAdapter: bind child element: item 0
D/ChildAdapter: bind child element: item 1
D/ChildAdapter: bind child element: item 0
D/ChildAdapter: bind child element: item 1

日志表示只构建了第一个和第二个元素,但我还想预构建第三个和第四个元素。

我也尝试使用 this,但它也不起作用

预取仅适用于滚动,不适用于第一个初始项目创建。

最后我使用自定义布局管理器覆盖 getExtraLayoutSpace 和 return 100000我的解决方案有潜在危险,但我使用它,因为我知道项目数不能超过 10 项。