UncaughtExceptionHandler

来源:互联网 发布:java枚举的声明 编辑:程序博客网 时间:2024/06/05 08:33

 如果使用默认的UncaughtHandler,则崩溃后会弹出 系统的『XX应用停止运行』对话框


自定义 unCaughtExceptionHandler

Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler());
public class ExceptionHandler implements Thread.UncaughtExceptionHandler {    @Override    public void uncaughtException(Thread thread, Throwable ex) {        ex.printStackTrace();    }}

不做特殊处理的情况下:界面不响应,数秒后弹出ANR框

------------------------------------------------

public class ExceptionHandler implements Thread.UncaughtExceptionHandler {    @Override    public void uncaughtException(Thread thread, Throwable ex) {        ex.printStackTrace();
        //同 System.exit(0);        Runtime.getRuntime().exit(0);    }}
直接退出程序

类似的:

android.os.Process.killProcess(android.os.Process.myPid());


----------------------------------------

PS:

是否重启?

当调用System.exit 或者 Process.KillProcess 的时候,首先会结束掉执行该方法所在的进程,然后根据结束掉该应用的时候的该应用的所有Task 状态来决定是否重启, 如果退出时该应用所有Task 中的TaskRecord 数量大于一 就会重启,小于或等于一不会重启,整个应用就结束掉了

重启后回到哪一个界面:

重启后会回到该应用的最上一个Task -当前显示的Task(因为一个应用可以有多个Task)中 栈顶的第二个TaskRecord(栈顶第一个将不会被重启),这也说明了为什么需要所有TaskRecord 的数量大于1的原因。

举例 1:

1:假如有一个App A ,  有3个Activity :ActivityA,ActivityB,ActivityC。启动顺序为A 启动B ,B启动C

2:首先通过Launcher 启动了A 。如果在A中通过某个点击事件或者在A的OnCreate or onStart  or onResum 方法,或者再A中按返回键的时候在OnStop or OnPause or OnDestroy 中触发了System.exit 或者 Process.KillProcess,那么程序将不会重启

3:如果 在A中启动了B ,并且A没有调用finish 方法,那么如果在B中的OnCreate or onStart  or onResum 方法或者再B中按返回键的时候在OnStop or OnPause or OnDestroy 中触发了System.exit 或者 Process.KillProcess,那么程序也将不会重启,只有当B 启动完成,对应的TaskRecord 已经添加的Task 中了才会重启回到ActivityA。

4:如果在B 中启动了C ,并且B 没有调用finish 方法,那么如果在C中的OnCreate or onStart  or onResum 方法或者再C中按返回键的时候在OnStop or OnPause or OnDestroy 中触发了System.exit 或者 Process.KillProcess,那么程序将会重启,但是重启后回到的界面是A 而非B,应为此时C还未添加到Task 或者已经从Task里面移除了,所以会重启回到除去栈顶的B 的下一个也就是A。当然如果C启动完成已经添加到了Task里面,在C中通过某个点击事件获取其他方式触发了System.exit 或者 Process.KillProcess那么会重启回到B


举例2:

1:有一个App B ,有5个Activity : A,B,C,D,E 。其中A是启动Activity,启动顺序为 A->B->C->D-E

2:假如C的activity:process = "com.test.process1",其他的Activity 使用默认的(名称和ApplicationID 一样),那么当A 启动了B 后B有启动了C ,只要是在C中不管任何地方调用了System.exit 或者 Process.KillProcess都会结束掉“com.test.process1”这个进程,其他进程不受影响,所以C Activity 

会关闭,但是A ,B 保持原样。因为C已经关闭了更具Task 里面的顺序所以显示B 界面(效果和按返回键一样,只是说按返回键不会结束掉进程);

3:接着第二种情况,假如不在C中调用,而是通过C启动了D,因为D 没有指定process ,所以D 和A,B 属于同一个进程。那么如果在D中执行了System.exit 或者 Process.KillProcess。那么会结束掉D所在的进程也就是默认名称的进程,而C 在的进程不受影响,因此再执行

System.exit 或者 Process.KillProcess后会显示C 界面不会立刻重启A,和B(???需要确定) ,只有在C界面按返回的时候,这时候发现B 已经关闭了所以系统会自动重启B ,在B  中按返回发现A也不存在了所以会自动重启A。针对此情况有一点需要补充一下,如果D 已经添加到Task 里面后执行的结束方法,那么回到C ,和上面所说的不矛盾(只是C不需要重启因为C在单独的进程可以解释得通),那么如果是在D还未添加到Task 的时候,那么此时Task 里面只有A,B,C 三个。那么为什么任然回到C呢? 而不是B 呢?是因为C 在单独的进程所以不受影响,而顺序决定了C 在B 上面,所有只有回到C而不是B

4:如果A,B,属于同一个进程,C,D,E 属于另一个进程,如果此时Task里面的状态时A-B-C-D-E。 E 在栈顶,那么在E 中执行了结束方法。会重启E 所在的进程回到界面D。在D中按返回重启C ,在C中按返回到B (不重启,不再同一个进程)

5:假如A,B,D 属于同一进程同一个Task 。C 在另一个进程并且另一个Task.那么当启动完成D后,整个应用就有两个Task 。最上一个(当前显示的)Task{TaskRecordA,TaskRecord,B,TaskReocedD},以及另一个Task{TaskRecordC}。那么在D中执行结束方法,会重启回到B界面,返回的顺序是B->A->C.其中B,A 会重启,C不会

总结:总的来说就是当调用System.exit 或者 Process.KillProcess的时候,只会结束当前调用的进程(如果一个应用有多个进程,其他进程不会发生改变,其他进程里面的activity 也不会重起),在根据结束之前整个应用的Tasks 状态(数量和顺序)来决定时候重启,数量决定是否重启,顺序决定重启后回到哪一个界面。




System.exit 和Process.killProcess区别

System.exit(code)  退出虚拟机

Causes the VM to stop running and the program to exit with the given exit status. If runFinalizersOnExit(boolean) has been previously invoked with a true argument, then all objects will be properly garbage-collected and finalized first.

Process.killProcess(pid)  结束进程

Kill the process with the given PID. Note that, though this API allows us to request to kill any process based on its PID, the kernel will still impose standard restrictions on which PIDs you are actually able to kill. Typically this means only the process running the caller's packages/application and any additional processes created by that app; packages sharing a common UID will also be able to kill each other's processes.

System.exit(0),System.exit(1)的区别:

参数0和1代表退出的状态,0表示正常退出,1表示异常退出(只要是非0的都为异常退出),即使不传0来执行也可以退出,该参数只是通知操作系统该程序是否是正常退出。


0 0
原创粉丝点击