之前对于activity的onSaveInstanceState方法的调用时机一直不是很理解,看到一些文章讲过onSaveInstanceState以下5种情况被调用:
- 当用户按下手机home键的时候。
- 长按手机home键或者按下菜单键时。
- 手机息屏时。
- FirstActivity启动SecondActivity,FirstActivity就会调用,也就是说打开新Activity时,原Activity就会调用。
- 默认情况下横竖屏切换时。
本文从源码的角度深入理解下改方法的执行时机。
众所周知,Android通过ActivityThread执行回调activity各个生命周期方法onPause/onStop等等。
通过分析ActivityThread的源码,得到在非人为销毁activity情况下(非按下返回键和调用finish方法情况下)onSaveInstanceState执行。
具体执行时机为:
- targetSdkVersion <(android 11)onPause前执行,
- targetSdkVersion >=(android 11)targetSdkVersion <(android 28) onStop前执行,
- targetSdkVersion >= android 28 onStop后执行。
接下来通过源码具体分析下
handlePauseActivity
@Override
public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges, PendingTransactionActions pendingActions, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(r, finished, reason, pendingActions);
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
mSomeActivitiesChanged = true;
}
}
/**
* Pause the activity.
* @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise.
*/
private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
PendingTransactionActions pendingActions) {
if (r.paused) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain cases.
// So here we likewise don't want to call onPause() if the activity
// isn't resumed.
return null;
}
RuntimeException e = new RuntimeException(
"Performing pause of activity that is not resumed: "
+ r.intent.getComponent().toShortString());
Slog.e(TAG, e.getMessage(), e);
}
//finished入参值通过android native c方法传递进来,在点击返回键和调用activity finish方法时候为true
if