Android アプリが OutOfMemory で落ちるときに確認を忘れがちなこと -> Bitmapのサイズ, src, View.INVISIBLE

確認した端末の環境

  • Galaxy S6
  • Android 6.0
  • 普段の空きメモリ 600m くらい

結論

  • 動的にリソース指定する ImageView に レイアウトしやすいからって xml 上の src に画像指定しない

アプリの内容と状況

  • 大体全画面くらいのサイズの画像を2枚 ViewPager で 1枚ずつ全画面表示するタイミングがある
    • Gallary のような。
    • 今後増えるので ViewPager を使用
  • 全画面大の画像は1枚あたりのサイズ 450k, 700k の png
  • 80k と 370 k の png があるページを足したら OutOfMemoryError が出るようになった
  • ViewPager での画像読み込みは Picasso 使用

当時の苦しみ

  • 全画面で表示したいので小さいサイズで読み込めない
  • そもそも 数百k 単位の画像数枚で OOM にまでなる ? 全部足しても 1.6m くらいなのに …
  • 全画面大の画像はファイルサイズ最大 700k だったけど View に入った Bitmap は 64m
    • bitmap だから当たり前だけど忘れていた…

作業内容

ログが長いので先に修正点から。 Android StudioAndroid Monitor -> Monitors タブで確認 - 80k, 370k の画像をとりあえず 30k と 90k に -> 最初のこのベージすら表示できなかったものがまずは表示できるように。 全画面の画像も読み込んで最大 220m allocated. - ViewPager で表示する fragment の Layout XML の Image View の src に 700k の png を指定していた -> もちろん画像は動的に java 側で指定しているので外した。外すだけで allocated 最大 160m. - 80k, 370k の画像は表示し終わったら非表示にするので View に setImageResource(0) 指定 -> allocated 160m で変わらず。 - 80k, 370k の画像は表示し終わったら非表示にするので View に setVisibility(View.INVISIBLE) を指定していたので View.GONE に変更 -> allocated のサイズは変わらず 160m

Log

80k と 370 k の画像のページから既に表示できない

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example, PID: 22875
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example/com.example.MainActivity}: android.view.InflateException: Binary XML file line #14: Binary XML file line #17: Error inflating class <unknown>
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3254)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350)
                      at android.app.ActivityThread.access$1100(ActivityThread.java:222)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:158)
                      at android.app.ActivityThread.main(ActivityThread.java:7237)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
                   Caused by: android.view.InflateException: Binary XML file line #14: Binary XML file line #17: Error inflating class <unknown>
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:551)
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:429)
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:380)
                      at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:474)
                      at android.app.Activity.setContentView(Activity.java:2387)
                      at com.example.MainActivity.onCreate(MainActivity.java:45)
                      at android.app.Activity.performCreate(Activity.java:6876)
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) 
                      at android.app.ActivityThread.access$1100(ActivityThread.java:222) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:158) 
                      at android.app.ActivityThread.main(ActivityThread.java:7237) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
                   Caused by: android.view.InflateException: Binary XML file line #17: Error inflating class <unknown>
                      at android.view.LayoutInflater.createView(LayoutInflater.java:657)
                      at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58)
                      at android.view.LayoutInflater.onCreateView(LayoutInflater.java:706)
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:774)
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716)
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:847)
                      at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
                      at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1001)
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:843)
                      at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810)
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:527)
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:429) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:380) 
                      at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:474) 
                      at android.app.Activity.setContentView(Activity.java:2387) 
                      at com.example.MainActivity.onCreate(MainActivity.java:45) 
                      at android.app.Activity.performCreate(Activity.java:6876) 
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) 
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) 
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) 
                      at android.app.ActivityThread.access$1100(ActivityThread.java:222) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:158) 
                      at android.app.ActivityThread.main(ActivityThread.java:7237) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
                   Caused by: java.lang.reflect.InvocationTargetException
                      at java.lang.reflect.Constructor.newInstance(Native Method)
                      at android.view.LayoutInflater.createView(LayoutInflater.java:631)
                      at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58) 
                      at android.view.LayoutInflater.onCreateView(LayoutInflater.java:706) 
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:774) 
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:847) 
                      at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) 
                      at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1001) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:843) 
                      at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:527) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:429) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:380) 
                      at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:474) 
                      at android.app.Activity.setContentView(Activity.java:2387) 
                      at com.example.MainActivity.onCreate(MainActivity.java:45) 
                      at android.app.Activity.performCreate(Activity.java:6876) 
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) 
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) 
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) 
                      at android.app.ActivityThread.access$1100(ActivityThread.java:222) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:158) 
                      at android.app.ActivityThread.main(ActivityThread.java:7237) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
                   Caused by: java.lang.OutOfMemoryError: Failed to allocate a 200450764 byte allocation with 16765264 free bytes and 140MB until OOM
                      at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
                      at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
                      at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:856)
                      at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:675)
                      at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:2228)
                      at android.content.res.Resources.loadDrawableForCookie(Resources.java:4215)
                      at android.content.res.Resources.loadDrawable(Resources.java:4089)
                      at android.content.res.Resources.loadDrawable(Resources.java:3939)
                      at android.content.res.TypedArray.getDrawable(TypedArray.java:886)
                      at android.widget.ImageView.<init>(ImageView.java:157)
                      at android.widget.ImageView.<init>(ImageView.java:145)
                      at android.widget.ImageView.<init>(ImageView.java:141)
                      at java.lang.reflect.Constructor.newInstance(Native Method) 
                      at android.view.LayoutInflater.createView(LayoutInflater.java:631) 
                      at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58) 
                      at android.view.LayoutInflater.onCreateView(LayoutInflater.java:706) 
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:774) 
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:716) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:847) 
                      at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) 
                      at android.view.LayoutInflater.parseInclude(LayoutInflater.java:1001) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:843) 
                      at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:810) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:527) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:429) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:380) 
                      at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:474) 
                      at android.app.Activity.setContentView(Activity.java:2387) 
                      at com.example.MainActivity.onCreate(MainActivity.java:45) 
                      at android.app.Activity.performCreate(Activity.java:6876) 
                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1135) 
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3207) 
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3350) 
                      at android.app.ActivityThread.access$1100(ActivityThread.java:222) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1795) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:158) 
                      at android.app.ActivityThread.main(ActivityThread.java:7237) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120) 
I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
I/System.out: (HTTPLog)-Static: isSBSettingEnabled false