简单的TextView.setText导致40%的CPU使用率

时间:2012-05-29 18:10:52

标签: android cpu-usage

运行我的应用程序会导致手机上的CPU使用率降低约40%:

final String position = String.format("%02d:%02d:%02d", time.getHours(), time.getMinutes(),
                time.getSeconds());
getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
         c.mTxtPosition.setText(position);
         ...

通过注释掉 setText 方法,CPU使用率降至预期的~4%。该方法每秒调用一次并刷新ImageViews,CustomViews ...而不会导致相同的负载过量。 除了CPU使用率之外,dalvik通过调用 setText()不断报告大约10-1000个对象的垃圾收集。

创建这样的跟踪文件:

Debug.startMethodTracing("setText");
c.mTxtPosition.setText(position);
Debug.stopMethodTracing();

traceview将以下方法列为各自独占CPU%的前5名:

  • ViewParent.invalidateChildInParent(16%)
  • View.requestLayout(11%)
  • ViewGroup.invalidateChild(9%)
  • TextView.setText(7%)
  • 顶层(6%)

有人对此有解释吗?

5 个答案:

答案 0 :(得分:19)

我不久前注意到了这一点,我认为问题在于每次调用setText时,文本框的大小都会发生变化,因此需要整个屏幕重新布局(昂贵)。

我自己还没有尝试过这个,但是如果你的文本框很简单并且可以做成相对固定的大小,也许可以尝试将TextView子类化并创建一个不在setText上调整自身大小的视图,而只是绘制无论它能进入现有区域?这样可以节省很多时间。

也许theres已经是setText的一个标志,可以让它做到这一点,但我不知道它,虽然我没有仔细搜索过。

答案 1 :(得分:2)

在我的情况下,我从触摸事件更新TextView,这会导致大量更新解决方案是更改TextView layout_width& layout_height到固定大小。

答案 2 :(得分:1)

一些可能的改进:

  1. 尝试使用一个处理程序,它每0.5秒更新一次textview,而不是执行它的线程。
  2. 使runnable成为最终的常量对象,而不是每秒钟一个新对象。
  3. 在告诉textview自行更新之前,请考虑检查时间是否已更改(newTimeInMs-LastPublishedTimeInMs> = 1000)。
  4. 而不是String.format,请尝试使用StringBuilder。但是,您不会喜欢String.format提供的语言环境解决方案(例如,对于阿拉伯数字)。

答案 3 :(得分:1)

如果您查看setText方法的源代码,您会发现它做了很多繁重的工作-有测量,图形和对象分配,所有这些都在主线程上运行。

您可以使用新的PrecomputedText API来在后台线程上完成所有这些操作,并使setText更快。

您可以使用kotlincoroutines

使用以下工作示例
private fun TextView.setTextAsync(text: String) {
    val textView = this
    lifecycleScope.launch {
        val params = TextViewCompat.getTextMetricsParams(textView)
        val precomputedText = withContext(Dispatchers.Default) {
            PrecomputedTextCompat.create(text, params)
        }
        TextViewCompat.setPrecomputedText(textView, precomputedText)
    }
}

有关更多详细信息,您可以在我的博客上阅读有关它的文章 https://androidexplained.github.io/android/ui/2020/10/21/improving-textview-settext-performance.html

答案 4 :(得分:0)

就我而言,它是TextView的这个属性:

android:ellipsize="marquee"

删除它会加快设置文本。