LoginSignup
20
25

More than 5 years have passed since last update.

OutOfMemoryError対策

Last updated at Posted at 2014-04-05

【Android】OutOfMemoryと戦う【OOM】に触発されたので自分なりの対策をまとめます。主にAndroid2.3系の話です。

メモリリークとWeakReferenceの話は省きます。

ヒープ外にBitmapをロード

BitmapをBitmapFactoryでロードする際に、隠しAPIのinNativeAllocを使ってヒープ外にBitmapをロードすることが出来ます。(Android2系まで)

BitmapFactory.Options options = new BitmapFactory.Options();
try{
    Field field = BitmapFactory.Options.getClass().getField("inNativeAlloc");
    field.set(options, true);
}catch(Exception e){
}

ヒープの拡大も行われないことから、純粋にロード時間の短縮にもなります。注意点として、LinuxのOOM-Killerに殺される可能性が出てきます。その際は例外をスローせずに静かにプロセスが終了します。

ActivityやService単位でプロセスを分離

プロセス単位で最大のヒープサイズが割り当てられていますので、プロセスを分離することでActivity単位で最大のヒープサイズまで使用することが出来ます。

http://developer.android.com/intl/ja/guide/topics/manifest/activity-element.html
AndroidManifest.xmlのActivityタグにprocess属性を付けることで、プロセスの分離が可能です。

プロセスの分離を行う際には変数のスコープに要注意です。static変数は同一プロセスの同一のクラスローダーの範囲で有効スコープです。最初のActivityのstatic変数にセットした値が、次のActivityで取得できなくなります。

大きなメモリ確保を行う際にtry/catch

あまりオススメできる方法ではありませんが、try/catchでOutOfMemoryErrorを捕まえるのも方法としてありです。(実際にAndroidのAPIの実装にも見ることが出来ます。)

try{
    //メモリを食う処理
}catch(OutOfMemoryError e){
    //代替の処理
}

AsyncTaskを過信しない

リストビューで画像を表示する際などにAsyncTaskを使うと思いますが、AsyncTaskは並列数の制限が大きいため、通信が遅い状態でスクロールをすると沢山スレッドが作成されます。適切に通信やタスクをキャンセルするか、Executors.newFixedThreadPoolで同時処理数が固定のスレッドプールを使うのがオススメです。

20
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
25