在循环内调用getResources()。getString(<string_id>,params)会降低性能

时间:2018-11-08 15:36:12

标签: android performance

我想知道在循环中调用getResources()。getString(,params)是否会降低性能。

我在$.payload[?(@.questionNumber == '1')].questionDefinitionId

中定义了以下字符串
strings.xml

在循环中我这样访问它

<string name="score">The score is %d</string>

我不知道textView.setText(getResources().getString(R.string.score, score)); 是如何在内部工作的,所以不确定长循环调用它是否是个好主意。

如果操作繁重,我可以在java类中使用getResources().getString(),但是我将为此字符串定义相关的本地化。

请建议这是否是不好的做法,并且有什么更好的方法。

1 个答案:

答案 0 :(得分:1)

回答此类问题的最佳方法是尝试一下并衡量结果。我做了这些字符串:

<string name="plain">Hello world</string>
<string name="variable">Hello %1$s</string>

然后,我制作了一个应用程序,该应用程序每个都加载一次,然后每个加载一千次,并测量所花费的纳秒数。我在运行旧版Android的旧版平板电脑上运行它,并得到了以下结果:

getString(R.string.plain);
getString(R.string.variable, "StackOverflow");
I/System.out(31427): Loading one plain string took 91,552 nanos
I/System.out(31427): Loading one variable string took 183,106 nanos
I/System.out(31427): Loading a thousand plain strings took 38,055,421 nanos
I/System.out(31427): Loading a thousand plain strings took 67,352,294 nanos

因此,一次加载带有格式参数的字符串需要0.18毫秒,而一次完成一遍完全相同的操作则需要67.35毫秒。我的结论是,反复加载相同的资源具有一些优化,但并不是令人难以置信的(不需要优化就花了我们三分之一的时间)。

我还使用String.format("Hello %s", "StackOverflow")测量了相同的测试,并得到了以下结果:

String.format("Hello %s", "StackOverflow");
I/System.out(31849): Formatting one variable string took 152,588 nanos
I/System.out(31849): Formatting a thousand variable strings took 22,613,526 nanos

因此,直接在Java中进行格式化一次尝试的速度略微快一些,但是在重复尝试时要快得多。

最后,一个弥合差距的测试。我使用getString()而不使用格式参数,然后使用String.format()进行格式化。这意味着我仅一次访问资源框架,但仍然可以获得国际化等带来的好处。这是我的结果

String template = getString(R.string.variable);
String.format(template, "StackOverflow");
I/System.out(32094): Formatting one variable string took 213,623 nanos
I/System.out(32094): Formatting a thousand variable strings took 28,015,135 nanos

在这里,一次调用是所有调用中性能最差的。这很有道理;我们正在手动完成之前“免费”获得的所有工作。但是,这样做一千遍仍然是每次从资源上加载的重大胜利。


总而言之,问题仍然归结于您在做什么,执行频率如何以及需要什么样的性能。考虑一下Android大约每16毫秒在屏幕上绘制一帧...从资源中加载一千个可变字符串会导致您跳过3-4帧。但是,如果只加载一百个字符串,那么您将不会跳过任何字符串。