方向改变时的 InflateException

InflateException on Orientation Change

每当我更改屏幕方向时,我的应用程序都会崩溃并出现以下异常。我相信它与导致模拟器 运行 内存不足的 ImageViews 有关,但我无法理解堆栈跟踪。

在 ProfileActivity.java(我希望改变方向)中,我尝试像这样保存和恢复我的 ImageViews 的实例,但它似乎不起作用:

@Override protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_beer_profile);

    if(savedInstanceState != null){
        ratingImages = (List<ImageView>) savedInstanceState.getSerializable("ratingImages");
    } 
}

@Override protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable("ratingImages", (Serializable) ratingImages);
}

@Override public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

}

但是,我得到以下 运行时间异常:

04-01 17:34:29.836 25455-25455/com.myapp.myapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp.myapp, PID: 25455
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp.myapp/com.myapp.myapp.ProfileActivity}: android.view.InflateException: Binary XML file line #269: Binary XML file line #269: Error inflating class <unknown>
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077)
  at android.app.ActivityThread.-wrap15(ActivityThread.java)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350)
  at android.os.Handler.dispatchMessage(Handler.java:102)
  at android.os.Looper.loop(Looper.java:148)
  at android.app.ActivityThread.main(ActivityThread.java:5417)
  at java.lang.reflect.Method.invoke(Native Method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: android.view.InflateException: Binary XML file line #269: Binary XML file line #269: Error inflating class <unknown>
  at android.view.LayoutInflater.inflate(LayoutInflater.java:539)
  at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
  at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
  at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:257)
  at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
  at com.myapp.myapp.ProfileActivity.onCreate(ProfileActivity.java:46)
  at android.app.Activity.performCreate(Activity.java:6237)
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077) 
  at android.app.ActivityThread.-wrap15(ActivityThread.java) 
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) 
  at android.os.Handler.dispatchMessage(Handler.java:102) 
  at android.os.Looper.loop(Looper.java:148) 
  at android.app.ActivityThread.main(ActivityThread.java:5417) 
  at java.lang.reflect.Method.invoke(Native Method) 
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: android.view.InflateException: Binary XML file line #269: Error inflating class <unknown>
  at android.view.LayoutInflater.createView(LayoutInflater.java:645)
  at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58)
  at android.view.LayoutInflater.onCreateView(LayoutInflater.java:694)
  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:762)
  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:835)
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:838)
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:838)
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:838)
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
  at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
  at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
  at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
  at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:257) 
  at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109) 
  at com.myapp.myapp.ProfileActivity.onCreate(ProfileActivity.java:46) 
  at android.app.Activity.performCreate(Activity.java:6237) 
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077) 
  at android.app.ActivityThread.-wrap15(ActivityThread.java) 
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) 
  at android.os.Handler.dispatchMessage(Handler.java:102) 
  at android.os.Looper.loop(Looper.java:148) 
  at android.app.ActivityThread.main(ActivityThread.java:5417) 
  at java.lang.reflect.Method.invoke(Native Method) 
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: java.lang.reflect.InvocationTargetException
  at java.lang.reflect.Constructor.newInstance(Native Method)
  at android.view.LayoutInflater.createView(LayoutInflater.java:619)
  at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58) 
  at android.view.LayoutInflater.onCreateView(LayoutInflater.java:694) 
  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:762) 
  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:835) 
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
  at android.view.LayoutInflater.inflate(LayoutInflater.java:515) 
  at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
  at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
  at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:257) 
  at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109) 
  at com.myapp.myapp.ProfileActivity.onCreate(ProfileActivity.java:46) 
  at android.app.Activity.performCreate(Activity.java:6237) 
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077) 
  at android.app.ActivityThread.-wrap15(ActivityThread.java) 
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) 
  at android.os.Handler.dispatchMessage(Handler.java:102) 
  at android.os.Looper.loop(Looper.java:148) 
  at android.app.ActivityThread.main(ActivityThread.java:5417) 
  at java.lang.reflect.Method.invoke(Native Method) 
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 
Caused by: java.lang.OutOfMemoryError: Failed to allocate a 4284912 byte allocation with 2835528 free bytes and 2MB 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.drawable.Drawable.createFromResourceStream(Drawable.java:1080)
  at android.content.res.Resources.loadDrawableForCookie(Resources.java:2635)
  at android.content.res.Resources.loadDrawable(Resources.java:2540)
  at android.content.res.TypedArray.getDrawable(TypedArray.java:870)
  at android.widget.ImageView.<init>(ImageView.java:152)
  at android.widget.ImageView.<init>(ImageView.java:140)
  at android.widget.ImageView.<init>(ImageView.java:136)
  at java.lang.reflect.Constructor.newInstance(Native Method) 
  at android.view.LayoutInflater.createView(LayoutInflater.java:619) 
  at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58) 
  at android.view.LayoutInflater.onCreateView(LayoutInflater.java:694) 
  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:762) 
  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:835) 
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
  at android.view.LayoutInflater.rInflate(LayoutInflater.java:838) 
  at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798) 
  at android.view.LayoutInflater.inflate(LayoutInflater.java:515) 
  at android.view.LayoutInflater.inflate(LayoutInflater.java:423) 
  at android.view.LayoutInflater.inflate(LayoutInflater.java:374) 
  at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:257) 
  at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109) 
  at com.myapp.myapp.ProfileActivity.onCreate(ProfileActivity.java:46) 
  at android.app.Activity.performCreate(Activity.java:6237) 
  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107) 
  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369) 
  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476) 
  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077) 
  at android.app.ActivityThread.-wrap15(ActivityThread.java) 
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) 
  at android.os.Handler.dispatchMessage(Handler.java:102) 
  at android.os.Looper.loop(Looper.java:148) 
  at android.app.ActivityThread.main(ActivityThread.java:5417) 
  at java.lang.reflect.Method.invoke(Native Method) 
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

编辑: 我在物理设备上试过了,它没有崩溃。但是,我仍然想知道如何在模拟器中最好地避免这个问题。我想 运行模拟器内存​​不足可能意味着我没有在方向更改时正确处理 ImageViews。

如有任何帮助,我们将不胜感激。谢谢!

I believe it has something to do with the ImageViews causing the emulator to run out of memory

更准确地说,您放入 ImageView 小部件的图像是崩溃的直接原因。

but I'm having trouble understanding the stack trace.

无论您在 com.myapp.myapp.ProfileActivity 中膨胀什么布局,在其 onCreate() 方法(第 46 行)中都有一个 ImageView 指向可绘制资源,加载时需要 4284912解码时的字节数。这相当于一张 1035px x 1035px 的图片。

这个比较大。

此外,您没有足够大的空闲内存块。部分原因是您已经消耗了大量内存,因为总体上只有 2MB 的堆 space 可用,更不用说单个块了。

I try to save and restore the instances of my ImageViews like this

那是不可能的。

战术上,看看布局,找到 ImageView 个小部件,找出哪些有非常大的图像,并停止使用那些非常大的图像。您可能还希望确认您正在使用的资源目录,并考虑为低密度屏幕使用低分辨率版本的图像。

从战略上讲,您需要掌控自己的内存消耗。您可以生成堆转储并使用 Android Studio(或其他地方)中的工具来查看您的堆中有什么以及占用了这么多 space。不幸的是,Google 没有费心在 Android Studio 中记录堆分析工具,但 this bit of documentation covers other aspects of memory management, and this page 涵盖了内存监视器,向您显示堆使用情况的实时图表(以及从哪里您可以通过工具栏按钮触发堆转储。