【问题标题】:Slow rendering of the most basic layout最基本布局的慢渲染
【发布时间】:2017-10-28 22:51:27
【问题描述】:

在我的 Android Vitals 中,有 30% 的用户体验到渲染缓慢。我的应用程序有一个非常复杂的 UI,所以我做了一个非常基本的项目来尝试解决这个问题。但事实证明,即使是最简单的布局,它也很慢。

布局是 Android Studio 作为模板提供的居中文本:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="match_parent"
    tools:context="slowrenderingtest.pichaipls.com.slowrenderingtest.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/timerView"
        android:text="00:00"
        android:textSize="40dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

使用布局的活动每秒都会更改文本(因为它是一个计时器):

Timer updateTicks = new Timer();
updateTicks.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Random r = new Random();
                timerView.setText(String.format("%02d", r.nextInt(60))+":"+
                                    String.format("%02d", r.nextInt(60)));
            }
        });
    }
}, 100, 1000);

当我打开 GPU 分析时,这非常接近在一些速度较慢的设备(显然是 30% 的用户)上绘制每帧的 16 毫秒限制。只有一个TextView。但这里有一个问题:当我第一次运行活动时,渲染时间很短,但几秒钟后它们就会迅速增加。如果我一直触摸屏幕(屏幕上没有控件),渲染时间仍然很低。我猜这是由于 CPU/GPU 进入低功耗状态(因此渲染需要更长的时间)。

我的问题是 Android Vitals。我一直看到有关缓慢渲染时间的警告(我认为任何超过 5% 的会话经历缓慢渲染都会收到警告),但我不知道如何加快速度。而且我担心这可能会影响我的应用排名,但即使是这个非常简单的例子,也有太多的 Android 用户使用慢速设备。

对此有什么办法吗?

【问题讨论】:

  • 你可以尝试运行 CPU 分析并找出哪个方法花费更多时间,我敢打赌它是 r.nextInt() 不应该在 UI 线程上过度使用
  • 不,它与 `r.nextInt()' 无关。如果我只显示一个递增的数字,问题也是一样的。事实上,对 CPU 征税似乎可以加快绘图速度。如果我不只是生成一个随机数,而是计算该数的阶乘,那么 GPU 更新缓慢的问题就会得到解决,尽管是以一种可怕且低效的方式。

标签: android performance


【解决方案1】:

我们遇到了同样的问题,但经过一番挖掘,我怀疑这是由于 CPU 闲置所致?

我们的情况类似。我们有一个 Runnable,在其中我们使用 Handler 每秒(仅)更新一个 TextView 的文本。 TextView 驻留在我们的 RecyclerView 中的一个项目上。有趣的是,当我们滚动页面,或者正在播放一些动画,或者在与应用程序交互时(基本上除了滴答声之外的任何其他东西),我们不会达到 16 毫秒的标记。但是让设备处于空闲状态,每帧需要 30-50 毫秒。

对于类似的情况,我们尝试了 SO 中提到的 different solutions。就像将 View 的宽度从 wrap_content 更改为 match_parent。没有帮助解决这个问题。我们尝试将 1000 毫秒间隔更改为 500、200、100、50、20、16、10,只有在使用 16/10 毫秒时才能看到更好的结果(CPU 一直在工作?)。

发现 this article 与 CPU 节流有关。那么可能当 CPU 空闲时,绘制帧需要更多时间?

如果您在 Android Studio 中查看 CPU 监视器,您会发现 CPU 在没有任何事情发生时立即变为空闲状态。 (更高的是当有交互时,并使用 Nexus 5)。

但是看看 GPU 监视器,它看起来与屏幕上的 Profile GPU 渲染条完全不同,实际上没有帧超过 16 毫秒标记!不确定哪个 GPU 监控是正确的。 (大的黄色是有互动的时候)。

【讨论】:

  • 是的,我已经提交了一个更新,其中 textview 每 50 毫秒左右更新一次。我会看看这是否能改善生命体征。如果确实如此,那将是 Google 有时令人叹为观止的无能的另一个例子。
  • 是的,每秒更新 60 次计时器可以解决问题。现在,它不再让手机进入低电量状态,而是不断工作以满足 Google 的“不良行为”指标。
  • @TimSim 我们尝试了这种方法,但由于它很耗电,我们得出的结论是这不是一种标准方法,我们可以修复他们的“不良行为”指标。所以我们决定暂时离开它。令人惊讶的是,即使代码基本相同,我们也不再在 Play Store 上看到冻结帧问题。可能他们改变了计算这些指标的方式。
  • 我说的不是冻结帧,而是缓慢的帧绘制时间。我实施的解决方案只是让应用程序像所有其他计时器应用程序(包括谷歌制造的那些)一样工作,每秒画帧 60 次,即使每秒一次是最佳的。电池消耗的差异是微不足道的。对于任何好奇的人来说,修复 Android Vitals 似乎不会对应用程序的下载产生太大影响(如果有的话)。
【解决方案2】:

尝试使 textView 在宽度上匹配父项...如果您每秒更改一次文本,则意味着 TextView 每次都需要计算其大小。你会对结果感到惊讶...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    • 2021-09-20
    相关资源
    最近更新 更多