关于 Activity 重建,我们探究几个问题:
- 当前 app 正在前台运行,不在栈顶的 Activity 有可能会因为系统资源,例如内存等不足回收吗?
- 当 app 处于后台运行,app 进程未被杀死,其内部的 Activity 会被回收吗?
- 当 app 处于后台运行,app 的进程会被杀死吗?
如果有能力,建议解释过程中可以配合源码,不一定要全部答出来~
更多问答 >>
-
每日一问 | 好奇ActivityThread中为什么会有一个 Application的集合?
2021-08-30 21:36 -
每日一问 | Gson中序列化对象的操作有低侵入的优化方案吗?
2021-12-02 00:50 -
每日一问 UndeclaredThrowableException 是什么异常?
2021-12-02 00:50 -
每日一问 | android hidden api 不是禁用反射,以及如何突破,「元反射」不行了?
2022-02-08 23:51 -
每日一问 | ViewModel 在什么情况下的「销毁重建」能够对数据进行无缝恢复?
2021-08-25 18:11 -
每日一问 | 我们经常说到的 Android 脱糖指的是什么?
2021-07-11 22:06 -
2021-07-11 22:06
-
每日一问 | Dialog 的构造方法的 context 必须传入 Activity吗?
2021-07-11 22:06 -
2021-05-28 00:29
问题1:会回收,写了个简单demo验证下。
MainActivity23有个button启动MainActivity24。MainActivity24不断增大内存会导致MainActivity23的onDestroy被执行。源码分析:API 版本30,Acvitity的问题应该是和ActivityThread和AMS有关系,从ActivityThread的main方法开始。
在ActivityThread的main方法中会新建ActivityThread实例,并通过attach方法和AMS产生联系。attach里面的BinderInternal.addGcWatcher会查看内存使用情况,当使用内存大于APP分配总内存的3/4时,就会触发ATMS去释放部分ActivityATMS(ActivityTaskManagerService)释放Activity方法 ,把可以回收的Activty的放进candidates列表,然后在通过transaction执行DestroyActivityItem来回收Activity。
ActivityRecode.java
生命周期方法调用这,Android 8以后有改动,不太明白怎么调用的可以去看看这篇文章https://juejin.cn/post/6844904040266989576还有个问题是通过BinderInternal.addGcWatcher添加的这个Runable何时执行的问题。可以通过BinderInternal源码发现,它运用了WeakReference和finalize的机制,WeakReference每次GC都会被回收,GcWatcher就会被调用finalize方法,然后执行上面添加的Runnable。在执行后再新建一个WeakReference供下次GC来重复运行该机制。
还有个问题是怎么触发的GC?
看了一圈,上面的forceGc方法嫌疑比较大,在ActivityThread中也有关于GC的对这个方法的调用(不太严谨哈,不对请大神指正)。requestConcurrentGC是一个native方法requestConcurrentGC方法源码),研究不动,去看调用forceGc的方法。在ActivityThread调用forceGc有两处,一个是handleLowMemory方法,一个是doGcIfNeeded方法一:先看doGcIfNeeded,在GcIdler的queueIdle被调用,GcIdler是一个IdleHandler,Handler消息队列空闲时被调用,GcIdler在scheduleGcIdler方法中被添加进消息队列。当handler收到GC_WHEN_IDLE消息时执行scheduleGcIdler,发送这个消息的方法是processInBackground。processInBackground方法在AMS中被调用。
AMS中performAppGcLocked调用了processInBackground,在这如果是进程的reportLowMemory为true,就会执行scheduleLowMemory。它就会发送LOW_MEMORY消息,去执行handleLowMemory方法,这就是forceGc第二个调用点。在performAppGcsLocked方法中会判断进程的优先级,如果比较低(ADJ值越大,优先级越低),或者进程是reportLowMemory,就会触发GC。ADJ优先级算法可以参考Gityuan大神的解读Android进程优先级ADJ算法。
在AMS的doLowMemReportIfNeededLocked方法中reportLowMemory被赋值为true。
所以问题1是可能会(如果顶层透明导致只是pause,就不会被回收?) 问题2:似乎后台和lowmem都会触发gcwatch 问题3:上图代码分析似乎没有涉及到进程销毁 ...查看更多
所以问题1是可能会(如果顶层透明导致只是pause,就不会被回收?) 问题2:似乎后台和lowmem都会触发gcwatch 问题3:上图代码分析似乎没有涉及到进程销毁
我直接点到OutOfMemory,之前的Activity也没destroy
严格来说确实是可能会,看releaseSomeActivities源码里,有条件是会直接return或者跳过部分Activity。只分析了第一个问题,没有分析2,3问。 ...查看更多
严格来说确实是可能会,看releaseSomeActivities源码里,有条件是会直接return或者跳过部分Activity。只分析了第一个问题,没有分析2,3问。
你可能是用的Android 10及以下的设备,Android 10和Android 11在releaseSomeActivities上实现不同,你可以看下他们的区别。 ...查看更多
你可能是用的Android 10及以下的设备,Android 10和Android 11在releaseSomeActivities上实现不同,你可以看下他们的区别。
有一种情况重建是在app运行过程中,切到设置将权限从允许状态改为禁止状态,这时app的所有进程都会重建,切回app时发现进程重建和栈顶的activity重建。会伴随一点时间的白屏。
观察了微信,没有白屏。有没有大佬知道微信这样是咋处理的。目前发现有两种解决方法:1、onCreate 中判断 savedInstanceState 是否为 null。在没有需求使用 savedInstanceState 的情况下,可以这么判断,因为 activity 重建时,安卓系统也会向 savedInstanceState 中传数据,比如 fragmentManager等等。但是如果有需求使用 savedInstanceState 存值的情况,那在判断 savedInstanceState 非空的同时,还需要判断是否有自身需求传入的 key。2、 在Application 定义一个Boolean类型的属性,isKilled = true 默认为true, 注册 ActivityLifecycleCallbacks 回调,在onActivityCreated 方法,先判断activity 是否是Launch ,若是则将Application.isKilled 赋值为false。若不是Launch 判断 Application.isKilled 是否为true, 若是true 说明 Application 被重建了,这时候跳转到Launch并杀掉刚重建的Activity。具体实现:自定义 PreventProcessKill 类,并实现 Application.ActivityLifecycleCallbacks 接口在 Application 中定义 默认为 true 的 isKilled 属性。
我认为第二种方法比第一种要好。
Android - 禁用权限后,进程被杀?activityCount 放在onActivityStopped 的话你少考虑了一种情况,activity 背景透明的话,放后台是不回调stop的
回复 Reginer
在基类onCreate中:可能不是很规范,但是能避免因为页面被回收导致的崩溃问题。我也观察过一些主流应用,页面被回收确实新新开页面的。
其实我已经不太关心activity生命周期了,jetpack解放了我
因为Activity回收导致的崩溃我遇到了数不胜数了,可惜至今也没探究出个所以然来,解决办法就是try了一下。
只能专业大佬回答了