ライブラリを賢く選択する
コレクションでコンテンツを整理
必要に応じて、コンテンツの保存と分類を行います。
アプリの最適化を有効にするには、Android の最適化と互換性のあるライブラリを使用する必要があります。ライブラリが Android の最適化用に構成されていない場合(関連する keep ルールをバンドルせずに反射を使用している場合など)は、Android アプリに適さない可能性があります。このページでは、一部のライブラリがアプリの最適化に適している理由と、ライブラリを選択する際の一般的なヒントを説明します。
反射よりも codegen を優先する
通常は、リフレクションではなくコード生成(codegen)を使用するライブラリを選択する必要があります。codegen を使用すると、オプティマイザーは実行時に実際に使用されるコードと削除できるコードをより簡単に特定できます。ライブラリが codegen とリフレクションのどちらを使用しているかを判断するのは難しい場合がありますが、いくつかの兆候があります。詳しくは、ヒントをご覧ください。
codegen とリフレクションの詳細については、ライブラリ作成者向けの最適化をご覧ください。
ライブラリを選択する際の一般的なヒント
ライブラリがアプリの最適化と互換性があることを確認するには、以下のヒントを参考にしてください。
最適化に関する問題を確認する
新しいライブラリを検討する場合は、ライブラリの問題トラッカーとオンライン ディスカッションを確認し、圧縮やアプリの最適化の構成に関連する問題がないか確認してください。ある場合は、そのライブラリの代替手段を探す必要があります。次の点に注意してください。
- AndroidX ライブラリや Hilt などのライブラリは、リフレクションではなく codegen を使用するため、アプリの最適化に適しています。リフレクションを使用する場合は、必要なコードのみを保持するように最小限の保持ルールを指定します。
- シリアル化ライブラリでは、オブジェクトのインスタンス化やシリアル化時にボイラープレート コードを回避するために、多くの場合リフレクションが使用されます。リフレクション ベースのアプローチ(JSON の Gson など)ではなく、codegen を使用してこれらの問題を回避するライブラリを探します。たとえば、代わりに Kotlin シリアル化を使用します。
- 可能であれば、パッケージ全体の保持ルールを含むライブラリは使用しないでください。パッケージ全体の keep ルールはエラーの解決に役立ちますが、広範な keep ルールは最終的に、必要なコードのみを保持するように絞り込む必要があります。詳細については、最適化を段階的に導入するをご覧ください。
新しいライブラリを追加した後に最適化を有効にする
新しいライブラリを追加したら、最適化を有効にしてエラーがないか確認します。エラーがある場合は、そのライブラリの代替手段を探すか、保持ルールを記述します。ライブラリが最適化に対応していない場合は、そのライブラリに関するバグを報告してください。
ルールは追加方式
保持ルールは累積されるため、つまり、ライブラリの依存関係に含まれている特定のルールは削除できず、アプリの他の部分のコンパイルに影響する可能性があります。たとえば、コードの最適化を無効にするルールがライブラリに含まれている場合、そのルールによってプロジェクト全体の最適化が無効化されます。
リフレクションの使用を確認する(上級)
ライブラリがリフレクションを使用しているかどうかは、コードを調べることで判断できる場合があります。ライブラリがリフレクションを使用している場合は、関連する keep ルールが提供されていることを確認します。ライブラリが次のことを行っている場合は、リフレクションを使っている可能性があります。
不適切な保持ルールを除外する(詳細設定)
本当に削除すべきコードを保持する keep ルールを含むライブラリは使用しないでください。ただし、使用しなければならない場合は、次のコードに示すようにルールを除外できます。
// If you're using AGP 8.4 and higher
buildTypes {
release {
optimization.keepRules {
it.ignoreFrom("com.somelibrary:somelibrary")
}
}
}
// If you're using AGP 7.3-8.3
buildTypes {
release {
optimization.keepRules {
it.ignoreExternalDependencies("com.somelibrary:somelibrary")
}
}
}
ケーススタディ: 最適化で Gson が破損する理由
Gson はシリアル化ライブラリですが、リフレクションを多用するため、アプリの最適化で問題が発生することがよくあります。次のコード スニペットは、Gson の一般的な使用方法を示しています。この方法では、実行時に簡単にクラッシュが発生する可能性があります。Gson を使用して User オブジェクトのリストを取得する場合、コンストラクタを呼び出したり、ファクトリーを fromJson()
関数に渡したりしません。次のいずれかを使用せずにアプリ定義クラスを作成または使用している場合、ライブラリがオープンエンドのリフレクションを使用している可能性があります。
- ライブラリ、標準インターフェース、またはクラスを実装するアプリクラス
- KSP などのコード生成プラグイン
class User(val name: String)
class UserList(val users: List<User>)
// This code runs in debug mode, but crashes when optimizations are enabled
Gson().fromJson("""[{"name":"myname"}]""", User::class.java).toString()
R8 がこのコードを分析し、UserList
または User
がインスタンス化されていない場合、フィールドの名前が変更されたり、使用されていないと思われるコンストラクタが削除されたりして、アプリがクラッシュする可能性があります。同様の方法で他のライブラリを使用している場合は、アプリの最適化に干渉しないことを確認してください。干渉する場合は、使用しないでください。
Room と Hilt はどちらもアプリ定義型を構築しますが、codegen を使用して反射の必要性を回避します。
このページのコンテンツやコードサンプルは、コンテンツ ライセンスに記載のライセンスに従います。Java および OpenJDK は Oracle および関連会社の商標または登録商標です。
最終更新日 2025-07-27 UTC。
[[["わかりやすい","easyToUnderstand","thumb-up"],["問題の解決に役立った","solvedMyProblem","thumb-up"],["その他","otherUp","thumb-up"]],[["必要な情報がない","missingTheInformationINeed","thumb-down"],["複雑すぎる / 手順が多すぎる","tooComplicatedTooManySteps","thumb-down"],["最新ではない","outOfDate","thumb-down"],["翻訳に関する問題","translationIssue","thumb-down"],["サンプル / コードに問題がある","samplesCodeIssue","thumb-down"],["その他","otherDown","thumb-down"]],["最終更新日 2025-07-27 UTC。"],[],[],null,["# Choose libraries wisely\n\nTo enable app optimization, you must use libraries that are compatible with\nAndroid optimization. If a library isn't configured for Android optimization---for\nexample, if it uses\n[reflection](https://en.wikipedia.org/wiki/Reflective_programming)\nwithout bundling associated keep rules---it might not be a good fit for an\nAndroid app. This page explains why some libraries are better suited for app\noptimization and provides general tips to help you choose.\n\nPrefer codegen over reflection\n------------------------------\n\nGenerally, you should choose libraries that use\n[code generation (*codegen*)](https://en.wikipedia.org/wiki/Code_generation_(compiler))\ninstead of reflection. With codegen, the optimizer can more easily determine\nwhat code is actually used at runtime and what code can be removed. It can be\ndifficult to tell whether a library uses codegen or reflection, but there are\nsome signs---see the [tips](#tips) for help.\n\nFor more information about codegen versus reflection, see\n[Optimization for library authors](/topic/performance/app-optimization/library-optimization#use-codegen).\n\nGeneral tips when choosing libraries\n------------------------------------\n\nUse these tips to help ensure that your libraries are compatible with app\noptimization.\n\n### Check for optimization issues\n\nWhen considering a new library, look through the library's issue tracker and\nonline discussions to check if there are issues related to minification or\nconfiguring app optimization. If there are, you should try to look for\nalternatives to that library. Keep in mind the following:\n\n- The [AndroidX libraries](/jetpack/androidx) and libraries such as [Hilt](/training/dependency-injection/hilt-android) work well with app optimization because they use codegen instead of reflection. When they do use reflection, they provide minimal keep rules to keep only the code that is needed.\n- Serialization libraries frequently use reflection to avoid boilerplate code when instantiating or serializing objects. Instead of reflection-based approaches (such as Gson for JSON), look for libraries that use codegen to avoid these problems, for example by using [Kotlin Serialization](https://github.com/Kotlin/kotlinx.serialization) instead.\n- Libraries that include package-wide keep rules should be avoided if possible. Package-wide keep rules can help resolve errors, but broad keep rules should eventually be refined to keep only the code that is needed. For more information, see [Adopt optimizations incrementally](/topic/performance/app-optimization/adopt-optimizations-incrementally).\n\n### Enable optimization after adding a new library\n\nWhen you add a new library, enable optimization afterwards and check if there\nare errors. If there are errors, look for alternatives to that library or write\nkeep rules. If a library isn't compatible with optimization, file a bug with\nthat library.\n\n### Rules are additive\n\nBe aware that keep rules are additive. This means that certain rules that a\nlibrary dependency includes cannot be removed and might impact the compilation\nof other parts of your app. For example, if a library includes a rule to disable\ncode optimizations, that rule disables optimizations for your entire project.\n\n### Check for use of reflection (advanced)\n\nYou might be able to tell if a library uses reflection from inspecting its code.\nIf the library uses reflection, check that it provides associated keep rules. A\nlibrary is probably using reflection if it does the following:\n\n- Uses classes or methods from the `kotlin.reflect` or `java.lang.reflect` packages\n- Uses the functions `Class.forName` or `classLoader.getClass`\n- Reads annotations at runtime, for example if it stores an annotation value using `val value = myClass.getAnnotation()` or `val value =\n myMethod.getAnnotation()` and then does something with `value`\n- Calls methods using the method name as a string, for example:\n\n // Calls the private `processData` API with reflection\n myObject.javaClass.getMethod(\"processData\", DataType::class.java)\n ?.invoke(myObject, data)\n\n### Filter out bad keep rules (advanced)\n\nYou should avoid libraries with keep rules that retain code that should really\nbe removed. But if you must use them, you can filter the rules out as shown in\nthe following code: \n\n // If you're using AGP 8.4 and higher\n buildTypes {\n release {\n optimization.keepRules {\n it.ignoreFrom(\"com.somelibrary:somelibrary\")\n }\n }\n }\n\n // If you're using AGP 7.3-8.3\n buildTypes {\n release {\n optimization.keepRules {\n it.ignoreExternalDependencies(\"com.somelibrary:somelibrary\")\n }\n }\n }\n\nCase study: Why Gson breaks with optimizations\n----------------------------------------------\n\nGson is a serialization library that often causes issues with app optimization\nbecause it heavily uses reflection. The following code snippet shows how Gson is\ntypically used, which can easily cause crashes at runtime. Notice that when you\nuse Gson to get a list of User objects, you don't call the constructor or pass a\nfactory to the `fromJson()` function. Constructing or consuming app-defined\nclasses without either of the following is a sign that a library might be using\nopen-ended reflection:\n\n- App class implementing a library, or standard interface or class\n- Code generation plugin like [KSP](https://github.com/google/ksp)\n\n class User(val name: String)\n class UserList(val users: List\u003cUser\u003e)\n\n // This code runs in debug mode, but crashes when optimizations are enabled\n Gson().fromJson(\"\"\"[{\"name\":\"myname\"}]\"\"\", User::class.java).toString()\n\nWhen R8 analyzes this code and doesn't see the `UserList` or `User` instantiated\nanywhere, it can rename fields, or remove constructors which don't seem to be\nused, causing your app to crash. If you are using any other libraries in similar\nways, you should check that they won't interfere with app optimization, and if\nthey do, avoid them.\n\nNote that [Room](/training/data-storage/room) and\n[Hilt](/training/dependency-injection/hilt-android) both construct app defined\ntypes, but use codegen to avoid the need for reflection."]]