2012-05-07 38 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

相关问题