2012-05-07 39 views
2

聯合a previous question 我想知道在發生異常時由Thread.UncaughtExceptionListener發生的情況到底會發生什麼。當聽者接收到未捕獲的異常時,上下文似乎陷入了一種無效狀態。它可以訪問其中的一些方法(主要是與資源有關的方法),但是其中很多方法不起作用(或者不明顯工作)。這包括(但不限於,我敢肯定有更多的我還沒有發現):新活動在線程捕獲UncaughtException之前上下文發生了什麼

  • Toast(在我的鏈接)
  • Dialog
  • 創新。這包括正常的Context.startActivity(Intent)PendingIntent

然而上下文仍具有上下文的資源(getString()Resources和奇怪的是Notification多個)表觀訪問。

這是爲什麼?是什麼導致這種狀態不平衡(?)在上下文中阻止任何上下文驅動的調用?

下面我爲您創建了一個測試應用程序,假設在未捕獲到異常時啓動錯誤活動。爲了測試我已經提到的事情(吐司和對話),將他們的建設者置於BoomMitActivity中以代替通知構建者。

在給出的示例中,活動錯誤輸出(它怎麼會不?),並在點擊Notification時啓動BoomMitActivtiy。但是,BoomMit的onCreate永遠不會被調用。

應用:

public class AndroidTestoActivity extends Activity implements UncaughtExceptionHandler { 
    @Override public void onCreate(Bundle icicle) { 
     super.onCreate(icicle); 

     Thread.setDefaultUncaughtExceptionHandler(this); 

     throw new RuntimeException("HAHAHAHA, I broke you"); 
    } 

    @Override public void uncaughtException(Thread arg0, Throwable arg1) { 
     finish(); 
     NotificationManager nm = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); 
     Notification note = new Notification(R.drawable.ic_launcher, "Boom!", System.currentTimeMillis()); 

     Intent i = new Intent(this, BoomMitActivity.class); 
     i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
     PendingIntent pi = PendingIntent.getActivity(this, 1, i, PendingIntent.FLAG_ONE_SHOT); 
     note.setLatestEventInfo(this, "Boom!", "Open BoomMitActivity", pi); 
     note.flags |= Notification.FLAG_AUTO_CANCEL; 

     nm.notify(1, note); 
     Log.d("TAG", "End"); 
    } 

    static class BoomMitActivity extends Activity { 
     @Override public void onCreate(Bundle icicle) { 
      super.onCreate(icicle); 
      TextView tv = new TextView(this); 
      tv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); 
      tv.setBackgroundColor(0xffff0000); 
      tv.setText("BoomMitActivity is the one true activity"); 
      tv.setTextColor(0xff00ffff); 
      setContentView(tv); 
     } 
    } 
} 

清單:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.testo" 
    android:versionCode="1" 
    android:versionName="1.0" > 

    <uses-sdk android:minSdkVersion="8" /> 

    <application 
     android:icon="@drawable/ic_launcher" 
     android:label="@string/app_name" > 
     <activity 
      android:name=".AndroidTestoActivity" 
      android:label="@string/app_name" > 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 
       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 

     <activity android:name="AndroidTestoActivity$BoomMitActivity" 
      android:label="I'm a real boy!" 
      android:taskAffinity="" 
      android:excludeFromRecents="true" 
      android:launchMode="singleTask"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN"/> 
       <category android:name="android.intent.category.LAUNCHER"/> 
      </intent-filter> 
     </activity> 
    </application> 
</manifest> 
+0

你爲什麼要將'BoomMitActivity'作爲'static'? – Ronnie

+0

@ userSeven7s您無法將嵌套活動聲明爲none static。我可以很容易地將它放在自己的類中,但是對於測試來說,只需在AndroidTestoActivity中進行測試就更簡單了。 – AedonEtLIRA

+0

太正常了嗎? – Ronnie

回答

3

沒有發生語境本身。如果您正在談論當您處於應用程序崩潰對話框狀態的情況下,那麼崩潰的線程正坐在那裏等待用戶按下按鈕並讓它繼續自殺。此時系統知道你的應用程序已被丟棄,只是等待用戶確認並最終終止。所以你真的應該假設你正在走出去,而不是依賴任何工作。

此外,如果這個崩潰來自主線程,那麼該線程現在坐在那裏等待用戶確認崩潰對話框,以便自殺。它並沒有坐在那裏處理它的信息循環,而是坐在那裏完全阻止等待自殺。將不會在該線程上計劃的任何工作將執行。對於主線程,這包括像Activity.onCreate(),Service.onStart()等組件的回調。對於任何線程,這包括爲與該線程關聯的窗口UI分派任何工作。再次,如果這是主線程,這可能意味着所有的用戶界面。

+0

好吧,這很有意義,謝謝。我只是希望能有一個更優雅的崩潰,而不是「奧普斯,我們很抱歉你的開發人員是白癡」。 – AedonEtLIRA

+0

你會認爲更優雅的是什麼? – hackbod

+0

只是消失,沒有任何警告或原因 - 使我點擊圖標3次,直到我意識到它只是不會去工作... 這就是iPhone如何做...我小孩,我的孩子! :) – Dan

相關問題