2

私は初めての Android アプリ (そして、過去 15 年間で初めての Java アプリ) を作成しています。エンコードされた文字列を受け取り、コードを描画操作に変換します。コードのいくつかはグラデーションの定義を表しており、これが私の質問に関するものです。

私が正しく理解していれば、関数中に何らかの種類の新しいオブジェクトを作成しようとするとonDraw(私の拡張Viewクラスのオーバーライド)、オブジェクトをキャッシュし、onDraw 中に新しいオブジェクトを決して割り当てないことを示唆する警告が lint によって出力されます。そこで、コード文字列で定義されたすべてのグラデーションのキャッシュを作成することにしました。そうすれば、同じコードを同じサイズで再描画する場合、そのコードで定義されたグラデーションを再割り当てする必要はありません。

のキー構造を定義しようとしたときに問題が発生し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.equalsnotを使用してください==

  3. Java はカスタム値の型をサポートしていません。すべてがヒープに割り当てられます。うまくいけば、いくつかの割り当てが最適化されて取り除かれますが、これは保証できず、多くの場合、明らかに適用できません。

基本的:

まず、「糸くず」はまさにそれです。警告でもありません。これは、開発しているプラ​​ットフォームに固有のガイドラインにすぎません。引き分けに自由に割り当てることができますが、毎回行うことは避けてください。描画中に新しい LinearGradient を作成する必要がある場合は、先に進みますが、後で作成する必要がないように保存してください。

次に、大量のシェーダーを作成しないようにするために、シェーダーでできる特別なことが 1 つあります。シェーダーを使用Shader.setLocalMatrixして移動したり、サイズを変更したりします。一部のシェーダーのサイズ変更で問題が発生しました (たとえば、RadialGradient では機能しないことはわかっています) が、運が良ければ機能する可能性があります。他のすべてが失敗した場合は、キャンバスのスタックに新しいマトリックスをプッシュすることにおそらくフォールバックします。

于 2013-07-08T11:15:30.613 に答える