2011-05-03 108 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 { 

      } 
     } 
    } 

} 
相關問題