【问题标题】:Recyclerview in Recyclerview scrolling first time laggyRecyclerview中的Recyclerview滚动第一次滞后
【发布时间】:2021-08-14 15:15:24
【问题描述】:

我有 Recyclerview 多种视图类型,并且第一次滚动滞后时在 Recyclerview 中有 Recyclerview 我不知道为什么第一次滚动滞后

这是我的布局片段

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/coordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".presentation.LottoFragment">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/teal_700"
        android:padding="20dp">

        <LinearLayout
            android:id="@+id/searchLinearLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <com.google.android.material.textfield.TextInputLayout
                android:id="@+id/menuTextInputLayout"
                style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/label">

                <AutoCompleteTextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:inputType="none" />

            </com.google.android.material.textfield.TextInputLayout>

        </LinearLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

    <LinearLayout
        android:id="@+id/contentLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:behavior_peekHeight="56dp"
        app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/ic_list_header_background"
            android:clickable="true"
            android:elevation="4dp"
            android:orientation="horizontal"
            android:padding="20dp">

            <TextView
                android:id="@+id/lotto_text_view"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fontFamily="@font/kanit_light"
                android:text="0 items(s)" />

            <ImageView
                android:id="@+id/filterIcon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="end"
                android:src="@android:drawable/arrow_up_float"
                android:visibility="gone" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/front_layer_linear_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"
            android:orientation="vertical">

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/lotto_recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipToPadding="false"
                android:paddingBottom="64dp"
                tools:itemCount="3"
                tools:listitem="@layout/item_lotto_prizes_one" />

        </LinearLayout>
    </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

这是我的片段

 lottoRecyclerView.apply {
            layoutManager = LinearLayoutManager(context)
            adapter = lottoLatestAdapter
        }

这是我的适配器:

class LottoLatestAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    companion object {
        private const val VIEW_TYPE_LOTTO_PRIZE_ONE = 1
        private const val VIEW_TYPE_LOTTO_PRIZE_RUNNING_NUMBER = 2
        private const val VIEW_TYPE_LOTTO_PRIZE_ONE_NEAR = 3
        private const val VIEW_TYPE_LOTTO_PRIZE_OTHER = 4
    }
    var latestList: MutableList<LottoPrizesLatestModel> = mutableListOf()
        set(value) {
            field = value
            notifyDataSetChanged()
        }

    private val viewPool : RecycledViewPool = RecycledViewPool()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        return when (viewType) {
            VIEW_TYPE_LOTTO_PRIZE_ONE -> {
                LottoPrizeOneHolder(ItemLottoPrizesOneBinding.inflate(inflater, parent, false))
            }
            VIEW_TYPE_LOTTO_PRIZE_RUNNING_NUMBER -> {
                LottoPrizeRunningNumberHolder(
                    ItemLottoRunningNumbersBinding.inflate(
                        inflater,
                        parent,
                        false
                    )
                )
            }
            VIEW_TYPE_LOTTO_PRIZE_ONE_NEAR -> {
                LottoPrizeOneNearHolder(
                    ItemLottoPrizesOneNearBinding.inflate(
                        inflater,
                        parent,
                        false
                    )
                )
            }
            VIEW_TYPE_LOTTO_PRIZE_OTHER -> {
                LottoPrizeOtherListHolder(
                    ItemLottoPrizesOtherListBinding.inflate(
                        inflater,
                        parent,
                        false
                    ),
                    LottoLatestPrizeOtherAdapter()
                )
            }
            else -> throw NullPointerException("Not have view Type")
        }
    }

    override fun getItemViewType(position: Int): Int {
        return when (latestList[position]) {
            is LottoPrizesLatestModel.LottoLatestPrizeOne -> VIEW_TYPE_LOTTO_PRIZE_ONE
            is LottoPrizesLatestModel.LottoLatestRunningNumbers -> VIEW_TYPE_LOTTO_PRIZE_RUNNING_NUMBER
            is LottoPrizesLatestModel.LottoLatestPrizeFirstNear -> VIEW_TYPE_LOTTO_PRIZE_ONE_NEAR
            is LottoPrizesLatestModel.LottoLatestPrizeOther -> VIEW_TYPE_LOTTO_PRIZE_OTHER
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is LottoPrizeOneHolder -> holder.bind(latestList[position] as LottoPrizesLatestModel.LottoLatestPrizeOne)

            is LottoPrizeRunningNumberHolder -> holder.bind(latestList[position] as LottoPrizesLatestModel.LottoLatestRunningNumbers)

            is LottoPrizeOneNearHolder -> holder.bind(latestList[position] as LottoPrizesLatestModel.LottoLatestPrizeFirstNear)

            is LottoPrizeOtherListHolder -> {
                viewPool.putRecycledView(holder)
                holder.bind(latestList[position] as LottoPrizesLatestModel.LottoLatestPrizeOther, viewPool)
            }

        }
    }

    override fun getItemCount(): Int = latestList.size
}

这是我的布局支架

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="8dp">

    <TextView
        android:id="@+id/title_prize_other_text_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fontFamily="@font/kanit_light"
        android:gravity="center"
        android:textSize="26sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/prize_other_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clipToPadding="false"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/title_prize_other_text_view"
        tools:itemCount="10"
        tools:listitem="@layout/item_lotto_prizes_other" />

    <GridLayout
        android:id="@+id/prize_other_grip_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:columnCount="2"
        android:orientation="vertical"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/title_prize_other_text_view" />

    <TextView
        android:id="@+id/text_prize_one_near_text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="@font/kanit_light"
        android:text="@string/lotto_prize_per_baht"
        android:textSize="16sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/prize_other_recycler_view" />

</androidx.constraintlayout.widget.ConstraintLayout>

这里是我在 RecyclerView 中的持有者 recyclerView

class LottoPrizeOtherListHolder(
    private val binding: ItemLottoPrizesOtherListBinding,
    private val lottoLatestPrizeOtherAdapter: LottoLatestPrizeOtherAdapter
) :
    RecyclerView.ViewHolder(binding.root) {

    fun bind(
        lottoLatestPrizeOther: LottoPrizesLatestModel.LottoLatestPrizeOther,
        viewPool: RecyclerView.RecycledViewPool
    ) = with(binding) {

        prizeOtherRecyclerView.apply {
            layoutManager = GridLayoutManager(
                context,
                2,
                GridLayoutManager.VERTICAL,
                false
            ).apply {
                initialPrefetchItemCount = lottoLatestPrizeOther.prizeModel.number.size
            }
            this.adapter = lottoLatestPrizeOtherAdapter
            setRecycledViewPool(viewPool)
        }
        lottoLatestPrizeOtherAdapter.numberList =
            lottoLatestPrizeOther.prizeModel.number.toMutableList()
        titlePrizeOtherTextView.text = lottoLatestPrizeOther.prizeModel.name
        textPrizeOneNearTextView.text = itemView.context.getString(
            R.string.lotto_prize_per_baht,
            lottoLatestPrizeOther.prizeModel.reward
        )
    }
}

我的问题是:当我第一次滚动 recyclerview 时它不流畅并且 logcat show recyclerview 跳过了 51 帧!适配器,但是当我到达 recyclerView 的末尾并向上滚动然后向下滚动时,它非常流畅,我的 recyclerview 只有 TextView !!!我该如何解决这个问题?

这是我的视频应用https://youtu.be/Li7aKWmEfXQ

【问题讨论】:

    标签: android android-studio kotlin android-fragments android-recyclerview


    【解决方案1】:

    在你的片段中应用 LayoutManager 后添加这个:

    lottoRecyclerView.setDrawingCacheEnabled(true);
    lottoRecyclerView.setItemViewCacheSize(myCacheSize);
    

    【讨论】:

    • 谢谢你我试试,但我的情况下它不起作用
    【解决方案2】:

    Jank 第一次出现的主要原因是它第一次将值动态加载到内存中。而一旦它关闭,它已经预先加载了一些元素

    你可以使用

    mRecyclerView.setHasFixedSize(true); 
    mRecyclerview.setNestedScrollingEnabled(false);
    

    在您的 kotlin 代码中

    或在您的 RecyclerView xml 中添加 android:nestedScrollingEnabled="false"

    【讨论】:

      猜你喜欢
      • 2021-05-11
      • 2023-04-06
      • 2018-01-30
      • 1970-01-01
      • 2014-10-08
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多