2

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

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

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

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

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

4

1 回答 1

1

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

  1. 不要在每个 onDraw 中创建新的 LinearGradients

  2. 是的,子字符串分配了一个新的字符串对象(一些小例外是空字符串 AFAIK)。由于在 Java 或 C# 中无法实际更改字符串对象的内容,因此必须为字符串创建一个新对象。这就是为什么在制作字符串时建议使用 StringBuilders 的原因。此外,您似乎来自 C# 背景,所以如果您还没有遇到过这个问题(6 个月后...),请记住不要String.equals使用==

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

基本上:

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

其次,你可以对着色器做一件特别的事情来避免大​​量使用它们:使用Shader.setLocalMatrix它来移动它并调整它的大小。我在调整某些着色器的大小时遇到​​了一些麻烦(例如,我知道它不适用于 RadialGradient),但如果幸运的话,它可能会起作用。如果一切都失败了,也许会退回到将新矩阵推入 Canvas 的堆栈。

于 2013-07-08T11:15:30.613 回答