=== 目次 ===
ソースコードを見直す
この後のセクションで大きなメモリ容量を確保する方法を紹介しますが、まずはソースコードを見直しましょう。特に以下のような工夫が存在します。- ループごとに無駄に変数を生成するのはやめる(使い回せる変数はループの外で宣言しておきましょう)
- Streamは使用し終わったらすぐにcloseする
- 巨大な画像は縮小してからImageViewに貼り付ける
- 不必要になったImageViewからは即座にリソースを削除する(nullをsetすればOK)
- Applicationオブジェクトに大容量の変数を作成しない
大きなメモリ容量を確保する
manifest.xmlのapplicationタグ内のandroid:largeHeapにtrueをセットすることで大きなメモリ容量を確保することができます。以下、サンプルコードです。
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.areseitestproject"
>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AreseiTestProject"
tools:targetApi="31"
android:largeHeap="true"
>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
18行目が該当箇所です。これで大きなメモリ容量を確保できるようになります。
最後は諦める
対処方法をいくつか紹介しましたが、OutOfMemoryは他のアプリ使用状況などにも左右されますので、出るときは出ます(実際、Firebase crashlyticsを眺めているとOutOfMemoryが発生したユーザがその後とくに再発してなかったりします)。対策をある程度したならば、必要以上に対策するのはあきらめて、OutOfMemoryをtry-catchして、ユーザに「メモリが少なくなっているので他のアプリを落としてくれ」などの情報を提供する方が建設的かもしれません。
なお、OutOfMemoryの例外は通常のException例外と同じtry-catchでは検出できないので注意しましょう。詳しくは以下の記事にまとめています。
