屏幕方向更改后应用程序崩溃 [英] Application crashes after screen orientation changed

查看:23
本文介绍了屏幕方向更改后应用程序崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了以下问题.启动后,应用程序工作正常 - 即使在更改屏幕方向后也是如此.该应用程序尚未准备好处理方向更改(例如替代布局等),因此仅出现旋转的默认布局并且没关系.但是,当我通过按返回键离开应用程序时,更改方向并在再次启动应用程序后立即崩溃.崩溃后,如果我再次启动应用程序,它会运行良好,直到出现前面描述的情况 - 然后它会崩溃.

I've got the following problem. After starting, application works fine - even after changing the screen orientation. The application is not yet prepared to handle orientation change (eg. alternative layout and so on), so just the rotated default layout appears and it's OK. However, when I leave the application by pressing the back key, change the orientation and immediately after start the application again, it crashes. After a crash, if I start application once again, it works well until the previously described circumstances occur - then it crashes.

我已将设备连接到计算机并在调试模式下运行应用程序.重新启动后,甚至在调用 onCreate 之前都会引发异常.崩溃调用堆栈如下:

I've connected the device to computer and run the application in debug mode. After restarting, an exception is thrown even before calling onCreate. The crash callstack follows:

Thread [<1> main] (Suspended (exception IllegalArgumentException))  
WindowManagerImpl.removeViewImmediate(View) line: 262   
Window$LocalWindowManager.removeViewImmediate(View) line: 436   
ActivityThread.handleDestroyActivity(IBinder, boolean, int, boolean) line: 4022 
ActivityThread.handleRelaunchActivity(ActivityThread$ActivityRecord, int) line: 4127    
ActivityThread.access$2400(ActivityThread, ActivityThread$ActivityRecord, int) line: 136    
ActivityThread$H.handleMessage(Message) line: 2183  
ActivityThread$H(Handler).dispatchMessage(Message) line: 99 
Looper.loop() line: 143 
ActivityThread.main(String[]) line: 5068    
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]  
Method.invoke(Object, Object...) line: 521  
ZygoteInit$MethodAndArgsCaller.run() line: 858  
ZygoteInit.main(String[]) line: 616 
NativeStart.main(String[]) line: not available [native method]  

我计划稍后处理屏幕旋转,但在那之前,我希望默认行为能够正常工作.

I plan to handle screen rotation later, but until then, I wish the default behavior to work correctly.

我只覆盖了 onCreate Activity 的方法.我还有自定义应用程序类,它创建了一个应用程序范围内使用的引擎类的实例:

I've overriden only the onCreate Activity's method. I've also got custom application class, which creates an instance of application-wide used engine class:

public class ProCalcApplication extends Application
{
    private Engine engine;

    public ProCalcApplication()
    {
        super();

        engine = new Engine();
    }

    public Engine getEngine()
    {
        return engine;
    }
}

如何解决这个问题?

我做了更多的测试.我已经注释掉了整个代码,只留下了 onCreate 方法的默认实现(super() + setContentLayout()).问题仍然存在,所以我注释掉了整个布局 XML,应用程序终于停止崩溃.我正在确定错误的条目,请稍候;)

I've done some more testing. I've commented out whole code, leaving only the default implementation of onCreate method (super() + setContentLayout()). The problem persisted, so I've commented out whole layout XML and the application finally stopped crashing. I'm in process of nailing down the faulty entry, please stand by ;)

我找到了原因,但没有解决办法.错误的 XML 代码如下:

I've found the cause, yet no solution. The faulty XML code follows:

<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">

    <android.gesture.GestureOverlayView android:id="@+id/gestureOverlay" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="3">
        <ViewFlipper android:id="@+id/contextArea" android:layout_width="match_parent" android:layout_height="match_parent">

        </ViewFlipper>          
    </android.gesture.GestureOverlayView>

</LinearLayout> 

有人可以尝试证明或反驳此代码在所描述的情况下失败吗?或者指出,我在哪里做错了;)

Can someone maybe try to prove or disprove, that this code fails in described circumstances? Or point out, where did I make a mistake ;)

我的环境:HTC Desire Z (2.2.1),使用 API 8.Eclipse 版本:Helios Service Release 2内部版本号:20110218-0911.

My environment: HTC Desire Z (2.2.1), API 8 used. Eclipse version: Helios Service Release 2 Build id: 20110218-0911.

缩短一点:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
        <ViewFlipper android:id="@+id/contextArea" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="3">                       
        </ViewFlipper>
</LinearLayout>

还有更多信息;模拟器中的 API 8:两次屏幕方向更改 (Ctrl+F12) 和应用程序崩溃.模拟器中的 API 10:两次屏幕方向更改,无论方向如何,屏幕都保持横向模式(但应用程序不会崩溃).

And a little more info; API 8 in emulator: two screen orientation changes (Ctrl+F12) and application crashes. API 10 in emulator: two screen orientation changes and the screen remains in landscape mode regardless of orientation (application does not crash, though).

我错过了什么?

推荐答案

我发现了,我错过了什么 :) 既然没人回答,我给大家留个答案,遇到同样问题的人.

I've found out, what did I missed :) Since no one answered, I'll leave an answer for everyone, who'll encounter the same problem.

事实证明,所描述的问题是一个众所周知的 Android 库错误:ViewFlipper 无法正确处理屏幕方向更改.它出现在 API 2.1 中并一直持续到 3.0,据信它已修复.不幸的是,今天的大多数智能手机都存在这个问题,因为它们通常搭载 2.2 或 2.3.

It turns out, that the problem described is a generally known Android libraries bug: ViewFlipper fails to handle screen orientation change properly. It have appeared in API 2.1 and continues until 3.0, where it is believed to be fixed. Unfortunatelly, most of today's smartphones suffer from this problem, as usually they have 2.2 or 2.3 onboard.

解决方案是手动处理屏幕方向更改(请参阅 Activity 在 Android 旋转时重启 ) 或使用 FrameLayout、视图可见性和动画类手动实现视图更改和动画.

The solution is either to handle screen orientation change manually (see Activity restart on rotation Android ) or implement the view changes and animations manually, using FrameLayout, view visibility and animation classes.

另一种是使用 Eric Burke 的 SafeViewFlipper 类:

Another one is to use Eric Burke's SafeViewFlipper class:

/**
 * Works around Android Bug 6191 by catching IllegalArgumentException after
 * detached from the window.
 *
 * @author Eric Burke (eric@squareup.com)
 */
public class SafeViewFlipper extends ViewFlipper {
  public SafeViewFlipper(Context context) {
    super(context);
  }

  public SafeViewFlipper(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  /**
   * Workaround for Android Bug 6191:
   * http://code.google.com/p/android/issues/detail?id=6191
   * <p/>
   * ViewFlipper occasionally throws an IllegalArgumentException after
   * screen rotations.
   */
  @Override protected void onDetachedFromWindow() {
    try {
      super.onDetachedFromWindow();
    } catch (IllegalArgumentException e) {
      Log.d(TAG, "SafeViewFlipper ignoring IllegalArgumentException");

      // Call stopFlipping() in order to kick off updateRunning()
      stopFlipping();
    }
  }
}

您可以在从代码创建布局时使用它,也可以将其嵌入到您的 xml 布局文件中(您必须完全限定它,例如 <com.myapp.SafeViewFlipper/>).

You can use it while creating the layout from the code as well as embed it into your xml layout file (you'll have to qualify it fully, eg. <com.myapp.SafeViewFlipper />).

另请参阅 http://code.google.com/p/android/issues/detail?id=6191 了解更多信息.

See also http://code.google.com/p/android/issues/detail?id=6191 for more informations.

这篇关于屏幕方向更改后应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆