我们已经分析过Activity的启动流程,从中也分析了Activity的生命周期。而其中有一个生命周期方法:onSaveInstanceState方法,今天我们主要讲解一下onSaveInstanceState方法的执行时机。 可能部分同学对Activity的onSaveInstanceState方法不是特别熟悉,这里我们简单介绍一下。onSaveInstanceState方法是Activity的成员方法,主要用于在Activity销毁时保存Activity相关的对象信息,而其执行的时机不是我们主动调用的,而是Android系统的framework帮忙调用的,而其调用的时机,可以参考android系统的介绍:
This method is called before an activity may be killed so that when it comes back some time in the future it can restore its state. For example, if activity B is launched in front of activity A, and at some point activity A is killed to reclaim resources, activity A will have a chance to save the current state of its user interface via this method so that when the user returns to activity A, the state of the user interface can be restored via {@link #onCreate} or {@link #onRestoreInstanceState}.
可以发现onSaveInstanceState方法会在Activity将要被kill的时候执行。O(∩_∩)O哈哈~,可能跟以前讲解的内容不是太对,我们看过不少文章都是说onSaveInstanceStatex方法会在Activity容易被销毁的时候执行。那么这里明明说的是当Activity被销毁的时候就会执行onSaveInstanceState方法,那么具体的情况是如何的呢?我们具体看一下源码吧,哈哈。
通过分析Activity的生命周期方法,我们知道onSaveInstanceState方法在onPause方法之后执行在onStop方法之前执行。这里我们首先看一下onPause方法的源码逻辑。
Activity在执行onPause方法的时候回回调ActivityThread的handlePauseActivity方法,不太熟悉的同学可以参考: android源码解析之(十四)-->Activity启动流程,文章中有对Activity生命周期的详细讲解。
好吧,先具体看一下ActivityThread.handlePauseActivity的源码:
private void handlePauseActivity(IBinder token, boolean finished,
boolean userLeaving, int configChanges, boolean dontReport) {
ActivityClientRecord r = mActivities.get(token);
if (r != null) {
//Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
if (userLeaving) {
performUserLeavingActivity(r);
}
r.activity.mConfigChangeFlags |= configChanges;
performPauseActivity(token, finished, r.isPreHoneycomb());
// Make sure any pending writes are now committed.
if (r.isPreHoneycomb()) {
QueuedWork.waitToFinish();
}
// Tell the activity manager we have paused.
if (!dontReport) {
try {
ActivityManagerNative.getDefault().activityPaused(token);
} catch (RemoteException ex) {
}
}
mSomeActivitiesChanged = true;
}
}
在方法体中我们除了执行一些其他的操作,然后在handlePauseActivity方法体中调用了performPauseActivity方法,这个方法就是具体执行回调pauseActivity操作的方法,既然这样我们在看一下performPauseActivity方法的实现:
final Bundle performPauseActivity(IBinder token, boolean finished,
boolean saveState) {
ActivityClientRecord r = mActivities.get(token);
return r != null ? performPauseActivity(r, finished, saveState) : null;
}
可以发现在performPauseActivity方法中首先判断ActivityClientRecord是否为空,然后又调用了performPauseActivity方法的重载方法:
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
boolean saveState) {
...
if (!r.activity.mFinished && saveState) {
callCallActivityOnSaveInstanceState(r);
}
...
}
可以发现,这里调用了callCallActivityOnSaveInstanceState方法,看名称可以发现这里应该回调的是Activity的onSaveInstanceState方法,但是这里执行之前有一个条件判断,首先会判断这里的Activity是否被finish?应为这时候刚刚执行onPause方法所以这里的mFinished变量为false,所以判断执行callCallActivityOnSaveInstanceState方法只要需要通过saveState变量来判断了,而这里的saveState方法是performPauseActivity方法传递过来的。。。。好吧,我们来看一下调用performPauseActivity方法时saveState变量是如何赋值的。回到我们的handlePauseActivity方法,看一下performPauseActivity方法是如何调用的:
performPauseActivity(token, finished, r.isPreHoneycomb());
可以发现saveState boolean变量是通过r.isPreHoneycomb方法赋值的,这里我们看一下IsPreHoneycomb方法是如何实现的:
public boolean isPreHoneycomb() {
if (activity != null) {
return activity.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.HONEYCOMB;
}
return false;
}
可以发现当我们的App设置的targetSdk版本号小于android versionCode 11也就是android3.0的时候返回为true,其他的时候返回为false,也就是说当我们App设置的targetVersion大于android3.0的时候才会执行callCallActivityOnSaveInstanceState方法,好吧,继续看一下callCallActivityOnSaveInstanceState方法是如何实现的:
private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
r.state = new Bundle();
r.state.setAllowFds(false);
if (r.isPersistable()) {
r.persistentState = new PersistableBundle();
mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
}
}
可以发现方法体主要调用了mInstrumentation的callActivityOnSaveInstanceState方法,既然这样,我们再来看一下callActivityOnSaveInstanceState方法:
public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
PersistableBundle outPersistentState) {
activity.performSaveInstanceState(outState, outPersistentState);
}
这里方法体中又回调了Activity的performSaveInstanceState方法。。。
final void performSaveInstanceState(Bundle outState) {
onSaveInstanceState(outState);
saveManagedDialogs(outState);
mActivityTransitionState.saveState(outState);
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onSaveInstanceState " + this + ": " + outState);
}
可以看到这里回调了Activity的onSaveInstanceState方法,这样经过一系列的方法回调之后我们就执行了onSaveInstanceState方法。
这样我们当只执行onPause方法的时候一般通过设置targetVersion控制是否执行onSaveInstanceState方法,当设置的targetVersionCode大于android3.0的时候默认不会执行onSaveInstanceState方法。
然后我们看一下当Activity执行onStop方法的时候是否会执行onSaveInstanceState方法,通过之前分析的Activity的启动流程,我们知道Actvitiy执行onStop方法会回调ActivityThread的handleStopActivity,这样我们先看一下handleStopActivity方法的实现:
private void handleStopActivity(IBinder token, boolean show, int configChanges) {
ActivityClientRecord r = mActivities.get(token);
r.activity.mConfigChangeFlags |= configChanges;
StopInfo info = new StopInfo();
performStopActivityInner(r, info, show, true);
if (localLOGV) Slog.v(
TAG, "Finishing stop of " + r + ": show=" + show
+ " win=" + r.window);
updateVisibility(r, show);
info.activity = r;
info.state = r.state;
info.persistentState = r.persistentState;
mH.post(info);
mSomeActivitiesChanged = true;
}
然后我们发现在方法performStopActivity方法中调用了performStopActivityInner方法,我们继续看一下performStopActivityInner方法的实现:
private void performStopActivityInner(ActivityClientRecord r,
StopInfo info, boolean keepShown, boolean saveState) {
...
if (!r.activity.mFinished && saveState) {
if (r.state == null) {
callCallActivityOnSaveInstanceState(r);
}
}
...
}
可以发现还是通过saveState变量来控制是否调用onSaveInstanceState,而这里的saveState变量是在performStopActivityInner方法调用的时候传递的,回到我们的handleStopActivity方法中关于performStopActivityInner调用的代码:
performStopActivityInner(r, info, show, true);
好吧,这里直接传值为true,这样我们执行Activity的stop方法一定执行onSaveInstanceState方法。
总结
onSaveInstanceState方法是Activity的生命周期方法,主要用于在Activity销毁时保存一些信息。
当Activity只执行onPause方法时(Activity a打开一个透明Activity b)这时候如果App设置的targetVersion大于android3.0则不会执行onSaveInstanceState方法。
当Activity执行onStop方法时,通过分析源码我们知道调用onSaveInstanceState的方法直接传值为true,所以都会执行onSaveInstanceState方法。
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。