2011-05-03 196 views
4

我遇到以下问题。启动后,即使在更改屏幕方向后,应用程序也能正常工作。应用程序尚未准备好处理方向更改(例如,替代布局等),因此只需旋转默认布局即可出现,并且没问题。但是,当我按下后退键退出应用程序时,请改变方向,并在再次启动应用程序后立即崩溃。在崩溃之后,如果我再次启动应用程序,它会很好地工作,直到之前描述的情况发生 - 然后它崩溃。屏幕方向更改后应用程序崩溃

我已将设备连接到计算机并以调试模式运行应用程序。重新启动后,即使在调用onCreate之前也会引发异常。崩溃callstack如下:

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] 

我打算稍后处理屏幕旋转,但在此之前,我希望默认行为正常工作。

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

public class ProCalcApplication extends Application 
{ 
    private Engine engine; 

    public ProCalcApplication() 
    { 
     super(); 

     engine = new Engine(); 
    } 

    public Engine getEngine() 
    { 
     return engine; 
    } 
} 

如何解决此问题?


我已经做了一些更多的测试。我已经注释掉了整个代码,只留下了onCreate方法(super()+ setContentLayout())的默认实现。问题依然存在,所以我已经评论了整个布局XML,并且应用程序最终停止了崩溃。我正在处理错误的输入,请耐心等待)


我找到了原因,但没有解决方法。出故障的XML代码如下:

<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> 

有人可以也许试图证明或反驳,该代码中所描述的情况下失败了呢?或者指出,我在哪里犯了一个错误;)

我的环境:HTC Desire Z(2.2.1),使用API​​ 8。 Eclipse版本: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:两个屏幕方向更改,屏幕保持横向模式,而不管方向如何(应用程序不会崩溃)。

我错过了什么?

+0

你跟测试什么设备?什么API级别?你有没有注意到你的引擎类是否正在重新初始化后定向更改启动?应该吗,还是不应该? – 2011-05-03 12:28:33

+0

HTC Desire Z. API级别8.在方向更改重新启动后,引擎未重新初始化;它不应该这样做,但如果它没有坏处(尽管性能下降很小)。 – Spook 2011-05-03 12:40:48

+0

您是否在重新启动时检查引擎是否为空?另外,您是否将ProCalcApplication专门注册为清单中应用程序的扩展? – 2011-05-03 13:53:19

回答

10

我发现了,我错过了什么:)因为没有人回答,我会为每个人留下一个答案,谁会遇到同样的问题。

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

解决方案是手动处理屏幕方向更改(请参阅Activity restart on rotation Android),或者使用FrameLayout手动实现视图更改和动画,查看可见性和动画类。

另一种是用埃里克·伯克SafeViewFlipper类:

/** 
* Works around Android Bug 6191 by catching IllegalArgumentException after 
* detached from the window. 
* 
* @author Eric Burke ([email protected]) 
*/ 
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/>)。

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

+0

我发现它停止引发此异常。该错误已经得到了解决。 Android 7.1.2,小米redmi 4x,miui全球8.5 – Sergio 2017-11-17 11:13:15

0

本工程为您

package com.palewar; 
import android.app.Activity; 
import android.app.ProgressDialog; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 

public class ThreadActivity extends Activity { 


    static ProgressDialog dialog; 
    private Thread downloadThread; 
    final static Handler handler = new Handler() { 

     @Override 
     public void handleMessage(Message msg) { 

      super.handleMessage(msg); 

      dialog.dismiss(); 

     } 

    }; 

    protected void onDestroy() { 
     if (dialog != null && dialog.isShowing()) { 
      dialog.dismiss(); 
      dialog = null; 
     } 
     super.onDestroy(); 
    } 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     downloadThread = (Thread) getLastNonConfigurationInstance(); 
     if (downloadThread != null && downloadThread.isAlive()) { 
      dialog = ProgressDialog.show(ThreadActivity.this, "", 
        "Signing in...", false); 
     } 

     dialog = ProgressDialog.show(ThreadActivity.this, "", 
       "Signing in ...", false); 

     downloadThread = new MyThread(); 
     downloadThread.start(); 
     // processThread(); 
    } 

    // Save the thread 
    @Override 
    public Object onRetainNonConfigurationInstance() { 
     return downloadThread; 
    } 


    static public class MyThread extends Thread { 
     @Override 
     public void run() { 

      try { 
       // Simulate a slow network 
       try { 
        new Thread().sleep(5000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       handler.sendEmptyMessage(0); 

      } finally { 

      } 
     } 
    } 

}