Android System.exit(code) and android.os.Process.killProcess(pid)或者发生RunTimeException 导致应用重启

关于 System.exit(code) and android.os.Process.killProcess(pid) 或者发生RunTimeException导致应用重启 的问题,由于没有找到正式官方的文档说明,所以本人通过代码进行了一系列测试发现了某些规律


有不对的请知晓者告知。


首先在android中一个进程对应一个dalvik vm 实例,一个应用可以有一到多个进程也就是对应一到多个dalvik vm instance。一个应用可以有一到多个Task,每个Task 里面可以有一到多个TaskRecord。每个TaskRecord 对应了一个Activity。


OK,再来看一下api 文档时如何解释这两个方法的:


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.

一个是Stop VM ,一个是Kill Process ,上面说了一个 进程对应一个 VM ,那么不管是调用哪一个方法都会用看到同样的效果


当我们在代码中调用System.exit 或者 Process.KillProcess 的时候肯定会结束掉当前线程,但是会不会重启应用就要根据你调用结束时整个属于这个应用的所有Task的状态来决定:

android中Task 是可以跨进程跨应用的,即不同应用的activity 可能运行在同一个Task  中,System.exit 或者 Process.KillProcess 是根据什么来决定是否重启?重启的时候又是回到的哪一个界面(Activity)的呢?哪些界面会被重启?哪些又不会被重启呢?分为以下几部来说明:


首先:

在每一个时刻Android 系统都有一个Task 列表,维护了当前系统中已启动的应用以及应用中各个界面(Activity)之间的顺序。比如:

Task 1 (App1)

--- taskrecord1 (Activity A) 栈顶

--- taskRecord2 (Activity B)栈底


Task 11(App1)

--- taskrecord1 (Activity c)

--- taskRecord2 (Activity d)


Task2(App 2)

--- taskrecord1 (Activity A)

--- taskRecord2 (Activity B)


Task2(App 3)

--- taskrecord1 (Activity C)

--- taskRecord2 (Activity D)


Task 有顺序,TaskRecord 也是有顺序的,假如当前Task 如上所说,那么 当前手机显示的就是 App1 这个应用程序的 ActivityA界面。


2:是否重启:

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


3::重启后回到哪一个界面:

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


3:哪些会被重启,哪些不会?

上面第二条说了会回到第一个Task 的栈中的第二个TaskRecord,如果栈中在第二个下面还有其他TaskRecord 。那么在按返回键的时候会重新执行下一个TaskRecord  对应Activity  的onCreate 方法,依次类推,直到栈底为止。




 注意: 如果再Activity 的生命周期中执行System.exit 或者 Process.KillProcess 方法的时候一定要注意,在OnCreate ,OnStart,OnResum 的时候栈中是还没有存在该Activity对应的TaskRecord (该Activity还未被添加进去),或者同样在OnPause,OnStop,onDestory 的时候,如果是按Back 那么该Activity  对应的Activity 对应的TaskRecord 在执行System.exit 或者 Process.KillProcess 之前就已经被移除栈了,即在这种情况下会重启回到这个Activity 的上一个的上一个Activity(如果存在的话,如果不存在着直接退出了整个程序)。



举例 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 状态(数量和顺序)来决定时候重启,数量决定是否重启,顺序决定重启后回到哪一个界面。


同样当发生RunTimeException 的时候和System.exit 或者 Process.KillProcess效果是一样的。


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮克桃在写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值