質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.10%

OutOfMemoryErrorの解決方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,194

score 16

OutOfMemoryErrorの解決方法

Androidでアプリを作成しています
下のaddBalloonというメソッド(人物画像付きの吹き出しを動的に作成したかった)を複数回呼び出すアクティビティがあるのですが、このアクティビティを開き、戻るボタン(intentで他のアクティビティに遷移)で画面を戻し、再度このアクティビティを呼び出すということを繰り返していると3回ほどでOutOfMemoryErrorが出てしまいます。Bitmap関連だろうと思いrecycle()してみているのですが、あまり効果がありません。addBalloonメソッドを複数回実行すると、最後のメソッドでのBitmapしか解放されていなかったりするのでしょうか...
当たり前なのですがaddBalloon内で最後にreleaseBitmap,releaseImageViewメソッドを呼び出すと画像は表示されなくなるのですがエラーは出なくなったので解放のタイミングなのかなと思います...
また、作成した戻るボタンではなくAndroidの機能として付いている戻るボタン?(画面左下の◁のことです)でアクティビティを戻し、再度表示するとエラーは出ないのですがintentで戻ることとは根本的に異なるのでしょうか、単純に勉強不足です...
largeHeapを使うといくらかマシにはなるのですが最終的にはエラーが出てアプリが落ちてしまうので根本的な解決策があれば教えていただきたいです。
色々調べてはみたのですが自分では力不足のようなので皆さんの知恵をお借りしたいです、よろしくお願いします。

 private void addBalloon(String str) {
        // get Layout
        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setOrientation(LinearLayout.HORIZONTAL);
        LinearLayout mikoLayout = new LinearLayout(this);
        mikoLayout.setOrientation(LinearLayout.VERTICAL);

        // get bitmap
        Resources r = getResources();
        bmp = BitmapFactory.decodeResource(r, R.drawable.miko);
        mask = BitmapFactory.decodeResource(r, R.drawable.circle);
        bitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.RGB_565);

        // clipping
        Canvas tempCanvas = new Canvas(bitmap);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        tempCanvas.drawBitmap(bmp, 0, 0, null);
        tempCanvas.drawBitmap(mask, 0, 0, paint);
        paint.setXfermode(null);

        // get View
        iv = new ImageView(this);
        iv.setImageBitmap(bitmap);

        TextView mikoTv = new TextView(this);
        mikoTv.setText("xxx");
        mikoTv.setTextSize(18);
        mikoTv.setGravity(Gravity.CENTER);

        TextView tv = new TextView(this);
        tv.setText(str);
        tv.setBackgroundResource(R.drawable.fukidashi);
        tv.setPadding(70, 30, 20, 30);
        tv.setTextSize(18);

        // get and set Layout
        LinearLayout lay = (LinearLayout) this.findViewById(R.id.textLayout);

        mikoLayout.addView(iv, 200, 200);
        mikoLayout.addView(mikoTv);
        linearLayout.addView(mikoLayout);
        linearLayout.addView(tv, WC, WC);

        lay.addView(linearLayout);
    }

    protected void onPause() {
        super.onPause();
        releaseImageView();
        releaseBitmap();
    }

    private void releaseBitmap() {
        if (bitmap != null) {
            bitmap.recycle();
            bitmap = null;
        }
        if (bmp != null) {
            bmp.recycle();
            bmp = null;
        }
        if (mask != null) {
            mask.recycle();
            mask = null;
        }
    }

    private void releaseImageView(){
        if(iv != null){
            iv.setImageDrawable(null);
        }
    }
09-16 18:05:40.566 23922-23922/com.example.xxx.myapplication E/art: Throwing OutOfMemoryError "Failed to allocate a 17640012 byte allocation with 13937704 free bytes and 13MB until OOM"
09-16 18:05:40.579 23922-23922/com.example.xxx.myapplication E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                      Process: com.example.xxx.myapplication, PID: 23922
                                                                                      java.lang.OutOfMemoryError: Failed to allocate a 17640012 byte allocation with 13937704 free bytes and 13MB until OOM
                                                                                          at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
                                                                                          at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
                                                                                          at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:609)
                                                                                          at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
                                                                                          at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:467)
                                                                                          at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:497)
                                                                                          at com.example.xxx.myapplication.BirthResultActivity.addBalloon(BirthResultActivity.java:209)
                                                                                          at com.example.xxx.myapplication.BirthResultActivity.showResult(BirthResultActivity.java:132)
                                                                                          at com.example.xxx.myapplication.BirthResultActivity.onCreate(BirthResultActivity.java:57)
                                                                                          at android.app.Activity.performCreate(Activity.java:5941)
                                                                                          at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
                                                                                          at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2358)
                                                                                          at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2464)
                                                                                          at android.app.ActivityThread.access$1000(ActivityThread.java:161)
                                                                                          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1371)
                                                                                          at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                          at android.os.Looper.loop(Looper.java:135)
                                                                                          at android.app.ActivityThread.main(ActivityThread.java:5438)
                                                                                          at java.lang.reflect.Method.invoke(Native Method)
                                                                                          at java.lang.reflect.Method.invoke(Method.java:372)
                                                                                          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:917)
                                                                                          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:712)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

addBalloon()中の「// get bitmap」の直前で  releaseImageView()とreleaseBitmap()を呼び出すと改善しませんか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/22 15:14

    使用する画像は同じものなのですが、その場合はaddBalloonの外でbitmapを読み込んでおき、addBalloon内で呼び出せば解放するものはこれ一つでいいのでしょうか...

    キャンセル

  • 2017/09/22 15:29

    同じ画像を使いまわすのなら、読み込みと解放を一回ずつにしてしまうことは可能かもしれません。
    「可能です」と言い切ることも出来ませんが、実現すれば色々効率が良いですね。

    キャンセル

  • 2017/09/22 15:36

    きちんと解放されているかはわかりませんがonCreate内で1回だけ読み込んでそれを呼ぶことでも同じ動作にできました、これとlargeHeapを使うことですぐに落ちることもなくなり、動作も軽いです。
    本当に助かりました、ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る