FastAdapter 和 ConstraintLayout 的滚动问题:跳过 211 帧

Scrolling issue with FastAdapter and ConstraintLayout: Skipped 211 frames

对于我的问题,我已经在 Github:

准备了 a very simple AndroidX test app

我在 MainActivity:

中使用非常好的 FastAdapter 库
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    RecyclerView recyclerView = findViewById(R.id.recyclerView);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    recyclerView.setAdapter(mFastAdapter);

    mFastAdapter.withSelectable(true);
    mFastAdapter.withOnClickListener((v, adapter, item, position) -> {
        item.details = !item.details;
        // pass item.details as payload to bindView to prevent flickering
        adapter.getFastAdapter().notifyAdapterItemChanged(position, item.details);
        return true;
    });

    List<MyItem> newList = new ArrayList<>();
    for (int i = 1; i < 10; i++) {
        MyItem item = new MyItem();
        item.gid = i;
        item.stamp = i;
        item.state1 = (i % 2 == 0 ? WON : LOST);
        item.score1 = (int) (Math.random() * 50);
        item.score2 = (int) (Math.random() * 50);
        item.finished = new Date().toString().substring(0, 10);
        newList.add(item);
    }

    DiffUtil.DiffResult diffResult = FastAdapterDiffUtil.calculateDiff(mItemAdapter, newList);
    FastAdapterDiffUtil.set(mItemAdapter, diffResult);
}

对于 the items layout,我将 ConstraintLayout 与 8 个 TextView 和 4 个 ImageView 一起使用:

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/details"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/details"
        android:layout_margin="8dp"
        app:layout_constraintBottom_toTopOf="@+id/guidelineTop"
        app:layout_constraintEnd_toStartOf="@+id/gid"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/plus_circle_gray" />

    <TextView
        android:id="@+id/gid"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginStart="8dp"
        app:layout_constraintBottom_toTopOf="@+id/guidelineTop"
        app:layout_constraintEnd_toStartOf="@+id/info"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/details"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/info"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintBottom_toTopOf="@+id/guidelineTop"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toEndOf="@+id/gid"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/photo"
        android:layout_width="80dp"
        android:layout_height="60dp"
        android:scaleType="centerInside"
        app:layout_constraintBottom_toTopOf="@+id/score1"
        app:layout_constraintEnd_toStartOf="@+id/guidelineMiddle"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guidelineTop" />

    <ImageView
        android:id="@+id/photo2"
        android:layout_width="80dp"
        android:layout_height="60dp"
        android:scaleType="centerInside"
        app:layout_constraintBottom_toTopOf="@+id/score"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guidelineMiddle"
        app:layout_constraintTop_toTopOf="@+id/guidelineTop" />

    <TextView
        android:id="@+id/score1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/given1"
        app:layout_constraintEnd_toStartOf="@+id/guidelineMiddle"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/photo" />

    <TextView
        android:id="@+id/score"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/given"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guidelineMiddle"
        app:layout_constraintTop_toBottomOf="@+id/photo2" />

    <TextView
        android:id="@+id/given1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/elo1"
        app:layout_constraintEnd_toStartOf="@+id/guidelineMiddle"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/score1" />

    <TextView
        android:id="@+id/given"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/elo2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guidelineMiddle"
        app:layout_constraintTop_toBottomOf="@+id/score" />

    <TextView
        android:id="@+id/elo1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/guidelineBottom"
        app:layout_constraintEnd_toStartOf="@+id/guidelineMiddle"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/given1" />

    <TextView
        android:id="@+id/elo2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/guidelineBottom"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guidelineMiddle"
        app:layout_constraintTop_toBottomOf="@+id/given" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guidelineMiddle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guidelineTop"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/board"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="1:1"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guidelineBottom" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guidelineBottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" />

</androidx.constraintlayout.widget.ConstraintLayout>

在移动设备 phone(我使用 Moto G2 和 Moto G4 Play)调试应用程序并滚动只有 10 个项目的列表时,我不断收到警告:

01-17 15:16:27.279 13947-13947/de.afarber.fasi I/Choreographer: Skipped 173 frames!  The application may be doing too much work on its main thread.
01-17 15:38:17.700 13947-13947/de.afarber.fasi I/Choreographer: Skipped 35 frames!  The application may be doing too much work on its main thread.
01-17 15:38:21.237 13947-13947/de.afarber.fasi I/Choreographer: Skipped 211 frames!  The application may be doing too much work on its main thread.
01-17 15:38:34.569 13947-13947/de.afarber.fasi I/Choreographer: Skipped 106 frames!  The application may be doing too much work on its main thread.
01-17 15:38:38.696 13947-13947/de.afarber.fasi I/Choreographer: Skipped 107 frames!  The application may be doing too much work on its main thread.

在我的真实应用程序中,我有其他布局的片段不会产生此类错误,所以我认为较旧的手机 phone 不是原因。我也不会滚动特别快或太慢。

我已经通过从 ConstraintLayout 切换到 LinearLayout 并使用少数 Space 元素来更好地对齐来解决滚动 RecyclerView 的性能问题 -

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="24dp"
    android:orientation="vertical"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/details"
            android:layout_weight="10"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:contentDescription="@string/details"
            app:srcCompat="@drawable/plus_circle_gray"
            />

        <TextView
            android:id="@+id/gid"
            android:textAlignment="center"
            android:textStyle="bold"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

        <TextView
            android:id="@+id/info"
            android:textAlignment="center"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Space
            android:layout_weight="10"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

        <ImageView
            android:id="@+id/photo1"
            android:scaleType="centerInside"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="60dp"
            />

        <ImageView
            android:id="@+id/photo2"
            android:scaleType="centerInside"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="60dp"
            />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Space
            android:layout_weight="10"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

        <TextView
            android:id="@+id/score1"
            android:textAlignment="center"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

        <TextView
            android:id="@+id/score2"
            android:textAlignment="center"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Space
            android:layout_weight="10"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

        <TextView
            android:id="@+id/given1"
            android:textAlignment="center"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

        <TextView
            android:id="@+id/given2"
            android:textAlignment="center"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Space
            android:layout_weight="10"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

        <TextView
            android:id="@+id/elo1"
            android:textAlignment="center"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

        <TextView
            android:id="@+id/elo2"
            android:textAlignment="center"
            android:layout_weight="40"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            />

    </LinearLayout>

    <ImageView
        android:id="@+id/board"
        android:layout_width="match_parent"
        android:layout_height="240dp"
        />

</LinearLayout>