2010-11-11 39 views
2

我已经设法使用DDMS(伟大的工具)将我的分配下降到几乎没有,这大大减少了我的GC每3分钟大约1或2。尽管如此,我并不开心,因为当你与它互动时,这些通常会在游戏中(在某些手机上)引起明显的延迟。ANDROID如何减少字符串分配

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

我基本上这样做:

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

发生这种情况一旦每一帧更新和HUD系统是模块化的,因此我在当我需要塞东西并且这可能导致4个或5 HUD元素分配字符串和DDMS中的AbstractStringBuilders。

任何方法来进一步减少这些或消除所有的字符串分配,只是重用一个字符串对象?

感谢, 阿尔伯特Pucciani

+1

如果GC造成延迟,听起来像是你做错了什么。将一个整数转换为一个字符串是一项极其微不足道的操作,因为它必须转换为字符串SOMEwhere EVENTUALLY,所以您无法做到这一点。 – Falmarri 2010-11-11 18:43:00

+0

drawText(..)也需要char []。使用它 - 请参阅@ tp0w3rn答案。 – 2010-11-11 19:08:33

+0

@Falmarri:这不是问题的分配:1字符串分配x 5 HUD元素x每秒40次x 10秒=等于大量剩余的垃圾。 @Peter Knego:谢谢,我甚至没有注意到tp0w3rn的答案,直到我重新阅读你的文章。 – 2010-11-11 20:25:28

回答

5

读你的问题使我想起我前一段时间阅读罗伯特·格林的文章之一。它几乎相同地讨论你的问题。 http://www.rbgrn.net/content/290-light-racer-20-days-32-33-getting-great-game-performance。跳到第33天,开始阅读。

+0

太棒了,谢谢你的回复,这正是我需要的。 – 2010-11-11 20:24:59

+0

真棒,完美的作品,再次感谢!我会给你投票,但我没有足够的声望。 – 2010-11-11 20:31:35

+0

你仍然可以接受我作为正确答案:)。很高兴我能帮上忙,我也是新来的。 – tp0w3rn 2010-11-12 00:46:27

5

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

+0

嗨,我考虑过这个,但是考虑到HUD元素经常变化,每秒可能4-5次(如定时器,条纹,分数变化等),它们仍然会是一大堆字符串分配,并且当启用调试控制台它更糟,因为我使用了大量的字符串。 – 2010-11-11 20:18:22

0

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

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

这里的真实需要什么:

首先,你需要能够以数字的整数分开,并将其转换,而无需创建String对象为char。假设您要将324的整数转换为三个单独的字符'3','2','4',以放置在文本char []中。你可以这样做的一种方法是取值324,并做一个模10来得到最低的数字。因此,324%10 = 4。然后将值除以10再做另一个mod 10以得到下一个数字。所以(十分之三百二十四)%10 = 2,(100分之324)%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]中的内容并不重要,它被认为是无效的。您可以使用字符映射继续更新文本[],并且不应该创建任何对象。

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