在HashMap中使用复合键为许多LinearGradient着色器优化onDraw

时间:2013-01-27 13:39:56

标签: java android performance hashmap

我正在编写我的第一个Android应用程序(以及过去15年来我的第一个Java应用程序)。它采用编码字符串并将代码转换为绘图操作。一些代码表示梯度定义,这是我的问题所关注的。

如果我理解正确,尝试在onDraw函数(我的扩展View类中的覆盖)期间创建任何类型的新对象将导致lint输出警告,表明您缓存对象而从不在onDraw期间分配新对象。所以我决定尝试对代码字符串定义的所有渐变进行缓存。这样,如果您以相同的大小重绘相同的代码,则不必重新分配该代码定义的渐变。

我在尝试定义HashMap的密钥结构时遇到了问题,我认为这是缓存的最佳结构。如果我可以简单地使用将渐变定义为键的代码片段(字符串),那将是很好的,但我认为这不会很好,因为如果图片重新调整大小,代码保持不变,但是渐变必须随着图片改变大小。因此,对于不同大小的相同渐变,我不能使用相同的键,或者每次调整图片大小时都必须清除缓存。

这导致我尝试为HashMap创建复合键。稍微阅读一下Java,我发现它不支持元组,就像我所知道的那样,像C#这样的值类型。因此,创建复合键的推荐方法是创建一个新类。所以我开始创建一个新类来表示复合键。然后我意识到我已经回到原点。如果我必须创建一个引用类型对象来表示键,lint会给我一个关于在onDraw期间分配内存的警告,对吧? (或者即使它没有,我将在onDraw期间分配内存,这是我们试图避免的。)

我需要一些专家建议。我是否会将山脉移动进行优化,而这种优化更多的是指导而不是规则,我应该根据需要创建渐变?我应该将代码用作HashMap密钥,并在每次更改大小时清除缓存吗?字符串操作(例如子字符串)是否需要我试图避免的内存分配? Java是否支持自定义值类型?我是否需要编写自己的HashMap替代品,它可以接受一系列值类型作为密钥而不分配堆内存?

1 个答案:

答案 0 :(得分:1)

不幸的是,没有办法(我确定你知道)设置LinearGradient的大小或颜色。缓存事物是我认为最好的选择。所以,让我澄清一些事情:

  1. 不要每次onDraw创建新的LinearGradients

  2. 是的,substring分配一个新的字符串对象(一些小的例外是空字符串AFAIK)。由于Java或C#中没有办法实际更改字符串对象的内容,因此必须为该字符串创建一个新对象。这就是为什么在制作字符串时建议使用StringBuilders。此外,您似乎来自C#背景,所以如果您还没有碰到(6个月后...... ),请记住使用String.equals而不是{{1 }} <!/ p>

  3. Java不支持自定义值类型。一切都在堆上分配。希望一些分配得到优化,但这不能得到保证,显然在许多情况下都不适用。

  4. 基本上:

    首先,“lint”就是这样。这甚至都不是警告。这只是您正在开发的平台的特定指南。随意分配抽奖,但尽量避免每次都这样做。如果您需要在绘制期间创建一个新的LinearGradient,请继续,但将其保存以供日后使用,以便您不必再次进行。

    其次,你可以使用Shaders做一件特别的事情来避免使用它们:使用==来移动它并调整它的大小。调整一些着色器时我遇到了一些麻烦(例如,我知道它不适用于RadialGradient),但如果你很幸运,它可能会起作用。如果所有其他方法都失败,也许可以回到将新矩阵推到Canvas的堆栈上。