ANDROID如何减少字符串分配

时间:2010-11-11 18:26:29

标签: android

我已经设法使用DDMS(很棒的工具)将我的分配降到了最低点,这大大减少了我的GC每3分钟大约1或2。尽管如此,我并不高兴,因为当你与它进行互动时,这些通常会导致游戏中的显着延迟(在某些手机上)。

使用DDMS,我知道分配是什么,它们是从用于显示游戏信息的整数转换为HUD的字符串。

我基本上是这样做的:

int playerScore = 20929;
String playerScoreText = Integer.toString(playerScore);
canvas.drawText(playerScoreText, xPos, yPos);

一旦每次帧更新并且HUD系统是模块化的,就会发生这种情况,因此我在需要时插入内容,这会导致4或5个hud元素在DDMS中分配字符串和AbstractStringBuilders。

任何方法可以进一步减少这些或消除所有String分配并只重用一个String对象?

谢谢, Albert Pucciani

3 个答案:

答案 0 :(得分:5)

阅读你的问题让我想起了很久以前我读过的Robert Greens的一篇文章。它几乎完全相同地讨论了你的问题。 http://www.rbgrn.net/content/290-light-racer-20-days-32-33-getting-great-game-performance。跳到第33天开始阅读。

答案 1 :(得分:5)

记住最后一个int分数及其字符串表示。在新框架上检查分数是否相同。如果相同,则无需创建新字符串 - 只需使用旧字符串。

答案 2 :(得分:0)

这是我过去所做的。这将消除字符串分配。

我创建一个大小至少与屏幕上需要显示的最大字符数一样大的char []。这意味着您应该选择游戏中可实现的最高分数。你现在拥有它的方式让你显示高达2 ^ 31-1的分数,这是非常巨大的,这对于游戏来说是不实际的。请记住,这是你的游戏,因此可以在游戏环境中将最高分数限制在更合理的范围内。选择几乎无法实现的数字。设置此限制将使您能够不必将大整数转换为String对象。

这是必需的:

首先,您需要能够分隔整数中的数字并将它们转换为char而不创建String对象。假设您要将324的整数转换为三个单独的字符“3”,“2”,“4”以放置在文本char []中。一种方法是通过取值324并使用mod 10来获得最低位数。所以324%10 = 4.然后将值除以10,再做另一个mod 10得到下一个数字。所以(324/10)%10 = 2,和(324/100)%10 = 3。

int score = 324;
int firstPlaceInt = score%10; // firstPlace will equal 4
int tensPlaceInt = (score/10)%10; // tensPlace will equal 2
int hundresPlaceInt = (score/100)%10; // hundredsPlace will equal 3

你必须在循环中完成上述操作,但这表达了你在这里尝试做什么的想法。

接下来,使用这些数字,您可以通过引用字符映射将它们转换为字符。一种方法是,您可以通过制作大小为10的char []并将值0 - 9放在索引0 - 9中来创建此字符映射。

char[] charMap = {'0','1','2','3','4','5','6','7','8','9',};

这样做:

int score = 324;
char firstPlace = charMap[score%10];
char tenslace = charMap[(score/10)%10];
char hundredsPlace = charMap[(score/100)%10];

将为得分中的3位数创建所需的字符。

现在,在所有这些之后,我会将最高分限制为99,999(或者在你的游戏中有意义)。这意味着我需要显示的最大“字符串”是“Score:xx,xxx”。这需要一个大小为13的char [](在本例中称之为文本)。使用“Score:”初始化前7个字符,这些字符永远不需要更改。

char[] text = new char[13];
text[0] = 'S';
text[1] = 'c';
text[2] = 'o';
text[3] = 'r';
text[4] = 'e';
text[5] = ':';
text[6] = ' ';

接下来的6个将根据得分而有所不同。请注意,您可能不一定要填写所有剩余的6个字符,因此您需要创建一个int(在此示例中称为scoreCount),它将告诉您char []文本中有多少字符实际与当前字符相关在比赛中得分。假设我需要显示“得分:324”,这只需要从13中取出10个字符。将得分为324的3个字符写入char [7]到char [9],并将scoreCount设置为10表示char []中的有效字符数。

int scoreCount = 7;
text[9] = charMap[score%10]; // This is firstPlace
text[8] = charMap[(score/10)%10]; // This is tensPlace
text[7] = charMap[(score/100)%10]; // This is hundredsPlace
scoreCount = 10;

您可能需要在循环中执行上述操作,但这应该表达您在此处尝试执行的操作的一般概念。

之后,您可以使用 drawText(char [] text,int index,int count,float x,float y,Paint paint)索引将为0, count 将为 scoreCount ,表示应绘制文本中的字符数。在上面的例子中,文本[10]到文本[12]的内容并不重要,它被认为是无效的。您可以继续使用字符映射更新text [],这不应该创建任何对象。

我希望这会有所帮助。上面的代码不是很强大,但我把它写成了更多的表达我想要表达的想法。您必须创建自己的循环并在代码中正确管理数据,但这总结了为避免使用Strings / StringBuilder / StringBuffer /等需要发生的操作的机制。