【问题标题】:Android recyclerview poor performance after API 27 to 29 MigrationAPI 27 到 29 迁移后 Android recyclerview 性能不佳
【发布时间】:2019-07-08 03:13:06
【问题描述】:

迁移应用程序以支持最新的 API 29。一切进展顺利,应用程序正常运行,除了一个令人费解的问题; recyclerview 使用 SQLite 查询填充,该查询可能检索 500 多条记录,并在如下所示的详细活动中显示结果。

这在 API 27 上一直运行良好,细节活动几乎立即打开和填充,而 sql 调用、活动代码和布局在 5 年内没有改变。但是,在 API 29 版本上,使用 相同的代码,应用需要 3+ 秒才能显示相同的数据

在大量测试和阅读Slow Rendering 之后,我认为我已经将其确定为 API 29 中的androidx.recyclerview:recyclerview:1.0.0 花费更长的时间来构建活动 UI 的输出,这可能是由于我糟糕的编码和/或布局结构.

这是我的R.layout.msgh_detail,由 .java 填充

<?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"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:layout_collapseMode="pin" />

</com.google.android.material.appbar.AppBarLayout>

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="75dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:orientation="vertical">

        <include
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            layout="@layout/msgh_detail_list" />

    </LinearLayout>

</androidx.core.widget.NestedScrollView>

<androidx.cardview.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/replyCard"
    android:layout_marginBottom="2dp"
    android:layout_marginLeft="@dimen/card_margin"
    android:layout_marginRight="@dimen/card_margin"
    android:layout_gravity="bottom"
    android:layout_alignParentBottom="true"
    android:touchscreenBlocksFocus="false">

    <LinearLayout
        style="@style/Widget.CardContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textMultiLine|textCapSentences"
            android:maxLength="250"
            android:ems="10"
            android:imeOptions="actionDone"
            android:id="@+id/msg_reply"
            android:hint="@string/msg_reply_hint" />
    </LinearLayout>

</androidx.cardview.widget.CardView>

<com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_anchor="@id/replyCard"
        app:layout_anchorGravity="top|right|end"
        android:layout_margin="8dp"
        android:src="@drawable/ic_send_white_24dp" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

这是通过 .java ViewHolder 包含 R.layout.msgh_detail_list_item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:gravity="center_vertical"
android:orientation="vertical">
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="24dp"
    android:orientation="horizontal">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_weight="0.97"
        android:id="@+id/DayMMdd"
        android:ellipsize="end"
        android:maxLines="1"
        android:hint="@string/day_mth_dte" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/arrivaltime"
        android:layout_marginLeft="8dp"
        android:hint="@string/Hour_min" />

    <ImageView
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:id="@+id/avatar"
        android:src="@drawable/status_1"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:longClickable="false" />

</LinearLayout>


<androidx.cardview.widget.CardView
    android:id="@+id/detail_cardview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardBackgroundColor="#ccecf9">

    <LinearLayout
        style="@style/Widget.CardContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/text2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAppearance="?attr/textAppearanceListItem"
            android:autoLink="web"
            android:textColorLink="#009933"
            android:layout_weight="0.97"
            android:text="@string/test_msg" />

    </LinearLayout>

</androidx.cardview.widget.CardView>

</LinearLayout>

显然,这里发生了很多事情,坦率地说,我很惊讶它运行得如此之好,或者至少在 androidx 和 API 版本 29 出现之前它确实如此......!

问题:问题是应用程序在 300 多个记录集上变得异常缓慢,我对如何修复它有点难过...

稍后修复! 在@martin-zeitler 提示之后修订了R.layout.msgh_detail,现在似乎可以正常工作并且几乎可以立即加载数据。

从包含布局中删除了整个 androidx.core.widget.NestedScrollView 块并替换为 androidx.recyclerview.widget.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"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.appbar.AppBarLayout
    android:id="@+id/appbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
        app:layout_collapseMode="pin" />

</com.google.android.material.appbar.AppBarLayout>

<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/detail_recyclerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginBottom="70dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

<androidx.cardview.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/replyCard"
    android:layout_marginBottom="2dp"
    android:layout_marginLeft="@dimen/card_margin"
    android:layout_marginRight="@dimen/card_margin"
    android:layout_gravity="bottom"
    android:layout_alignParentBottom="true"
    android:touchscreenBlocksFocus="false">

    <LinearLayout
        style="@style/Widget.CardContent"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:inputType="textMultiLine|textCapSentences"
            android:maxLength="250"
            android:ems="10"
            android:imeOptions="actionDone"
            android:id="@+id/msg_reply"
            android:hint="@string/msg_reply_hint" />
    </LinearLayout>

</androidx.cardview.widget.CardView>

<com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_anchor="@id/replyCard"
        app:layout_anchorGravity="top|right|end"
        android:layout_margin="8dp"
        android:src="@drawable/ic_send_white_24dp" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

【问题讨论】:

  • 是的,如果您使用 androidx,就会发生这种情况。
  • 您应该提供的代码应该最少minimal reproducible example
  • 好的 @rob 为你修改了它更短:o)
  • 别为我做。 这是一项要求,正如我在 SO 规则的链接中向您展示的那样。
  • 哦@rob希望去掉减号-_-

标签: android android-recyclerview


【解决方案1】:

还注意到有一次,它变得相当迟钝......

问题很可能是NestedScrollView > LinearLayout > RecyclerView

另外,include 非常没用,只包含一个节点......你必须像这样嵌套它:

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:isScrollContainer="true"
    android:longClickable="false"
    android:measureAllChildren="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerview"
        tools:listitem="@layout/cardview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:color="?android:colorControlHighlight"
        android:fastScrollEnabled="true"
        android:gravity="start"
        android:scrollbarStyle="insideInset"
        android:scrollbars="vertical"
        android:splitMotionEvents="false"
        android:verticalScrollbarPosition="right"/>

</androidx.core.widget.NestedScrollView>

【讨论】:

  • @rangi 这样的错误很难追踪,因为只能应用试错法。
  • @rangi NestedScrollView 在拥有AppBarLayout 时是必需的。你只是缺少属性app:layout_behavior ...不会编辑任何东西。
  • 谢谢@martin-zeitler 哦,它仍然落后,所以我完全抛弃了NestedScrollView,这一切都变得生动起来(请参阅我问题末尾的修订版面)。您的提示是有效的,让我走上了一条道路,它奏效了......非常感谢。干杯,西蒙娜
猜你喜欢
  • 2021-11-27
  • 1970-01-01
  • 2020-05-22
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 2019-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多