デフォルトでは、R8 はパフォーマンスとサイズを改善するために多くの最適化を行いますが、最適化がアプリですぐに機能しないことがあります。大規模なアプリで R8 を初めて有効にする(またはフルモードを有効にする)場合は、最適化を段階的に導入することをおすすめします。難読化を一時的にオフにして、アプリ内のすべてのコードではなく、コードの一部に対して R8 を有効にします。この段階的なアプローチはローカル開発中に行うことをおすすめしますが、内部 QA テスト中や、段階的なロールアウトとして製品版でも使用できます。具体的な手順は、希望するタイムラインと、プレリリース テストのカバレッジに対する信頼度によって異なります。
最適化を制限する
R8 は、コードの削除、コードの書き換え、リソースの削除など、さまざまな種類の最適化を行います。最適化の種類の大まかな説明は次のとおりです。
- コードの圧縮(ツリー シェイキング): 参照されていないコードを削除します。
- 難読化(または識別子の圧縮): クラスとメソッドの名前を短くします。
- 最適化: コードの書き換え(インライン化など)
エラーの発生を減らすには、最初はこれらの最適化の一部のみを有効にします。
ツリー シェイキングのみを有効にする
コードの圧縮(ツリー シェイキング)では、参照されていないように見えるコードが削除されます。最も簡単な方法であるため、まずはツリー シェイキングから始めることをおすすめします。
ツリー シェイクのみを有効にするには、proguard-rules.pro
ファイルに以下を追加して、他のタイプの最適化をオフにします。難読化をオフにすると、スタック トレースを簡単に読み取れるため、これは重要です。
-dontobfuscate // Use temporarily to turn off identifier minification
-dontoptimize // Use temporarily to turn off optimization
最終的には、この構成を配布することはおすすめしません。これは、R8 がコードを最適化する能力を大幅に制限するためです。ただし、問題を修正する必要がある大規模なコードベースで R8 を初めて導入する場合は、この構成を開始点として使用することをおすすめします。
互換モードを使用する
デフォルトでは、R8 はフルモードで実行されます。フルモードではパフォーマンスとサイズが大幅に改善されますが、初めて圧縮を有効にする場合は、一時的に無効にして代わりに互換モードを使用できます。
互換モードを使用するには、gradle.properties
ファイルで次の設定を使用します。
android.enableR8.fullMode = false // Use temporarily to disable full mode
残りの最適化を有効にする
アプリでツリー シェイキングが機能していることを確認したら、上記の設定を削除して、難読化、最適化、R8 フルモードを再度有効にできます。難読化を行うとデバッグが難しくなる可能性があるため、最初にツリー シェイキングの問題に対処することをおすすめします。
スタック トレースの難読化解除の詳細については、元のスタック トレースを復元するをご覧ください。
最適化の範囲を制限する
完全最適化ビルドでは、すべてのライブラリとパッケージのすべてのコードが最適化されるため、R8 を初めて有効にしたときに問題が発生することはよくあります。アプリの一部で最適化に問題が見つかった場合は、R8 を完全にオフにしないでください。他の部分でメリットを失うことになります。代わりに、問題の原因となっているアプリの部分でのみ R8 を一時的に無効にします。
パッケージ全体の keep ルールを使用する
アプリの一部で R8 を一時的に無効にするには、パッケージ全体の keep ルールを使用することをおすすめします。これらの最適化の問題は後で必ず修正する必要があります。これは通常、問題のある領域を回避するための暫定的な解決策です。
たとえば、アプリの一部で Gson を大量に使用していて、最適化に問題が発生している場合は、ターゲット設定された keep ルールを追加するか、codegen ソリューションに移行するのが理想的な修正方法です。ただし、アプリの残りの部分の最適化をブロックしないようにするには、Gson 型を定義するコードを専用のサブパッケージに配置し、次のようなルールを proguard-rules.pro
ファイルに追加します。
-keep class com.myapp.json.** { *; }
使用しているライブラリに内部コンポーネントへのリフレクションがある場合は、同様にライブラリ全体に keep ルールを追加できます。保持する適切なパッケージを見つけるには、ライブラリのコードまたは JAR/AAR を調べる必要があります。繰り返しになりますが、これは長期的に維持することはおすすめしませんが、アプリの残りの部分の最適化の妨げになる可能性があります。
-keep class com.somelibrary.** { *; }
パッケージ全体の保持ルールを削除する
パッケージ全体の keep ルールでアプリが正しく機能したら、戻ってターゲット タイプの keep ルールを追加するか、そもそも keep ルールを必要とするリフレクションの使用またはライブラリを削除する必要があります。
たとえば、関連するクラスのみを保持するために、特定のクラスを拡張するすべてのルールを保持することは、AndroidX では非常に一般的です。通常、リフレクションは、特定の抽象クラスを拡張するクラス、特定のインターフェースを実装するクラス、特定のランタイム アノテーションを持つクラスのみをターゲットにする必要があります。これらの各方法は、最終的な完全に最適化されたアプリでパッケージ全体の保持ルールが必要ないように、保持ルールを定義するためのサポートされている方法です。