2024年鸿蒙最全Activity的生命周期和启动模式详解(3),2024年最新HarmonyOS鸿蒙工程师面试题

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

生命周期流程图

拓展问题:
1.onStart和onResume,onPause和onStop有什么实质上的不同?

onStart 和 onStop 是从 Activity 是否可见角度来回调的,而 onResume 和 onPause 是从Activity是否位于前台来回调的。

2.A 启动 B,那么 B 的 onResume 和 A 的 onPause 哪个先执行?

结论:A 先执行 onPause() 方法,紧接着 B 执行 onCreate() -> onSatar() -> onResume() 方法,接着执行 A的 onStop()

原因:

启动 Activity 的请求有 Instrumentation 通过 Binder 接口向 AMS 发送请求,AMS 内部维护着一个 ActivityStack 并负责栈内 Activity 的状态同步,接着 AMS 通过 IApplicationThread( 位于当前应用进程内) 的 Binder 接口去同步 Activity 的状态从而完成生命周期方法的调用。

调用 ApplicationThread.scheduleLaunchActivity 通过 handle.sendMessage 通知 ActivityThread 完成新Activity 的 onCreate,onStart,onResume的调用过程。

ActivtyStack.resumeTopActivityInnerLocked();//
---TaskDisplayArea.pauseBackStacks();//暂停所有堆栈或仅后堆栈中的所有活动
----ActivtyStack.startPausingLocked();//开始暂停当前处于 resumed 的活动
------ActivityStackSupervisor.realStartActivityLocked();

.... app 进程
ActivtyThread.handleLaunchActivity(){
----ActivtyThread.performLaunchActivity();
----1.ContextImpl appContext = createBaseContextForActivity(r);//创建该 context实现类
----2.mInstrumentation.newActivity();//通过appContext类加载器反射创建Activity
----3.LoadedApk.makeApplication();//创建application
----4.appContext与activity相关联
----5.执行activity.attach()方法。
----6.mInstrumentation.callActivityOnCreate();//执行oncreate方法 

2. 异常情况下的生命周期:

1.系统配置发生改变导致Activity被杀死并重新创建

异常终止:点击了返回键 ,锁屏 ,点击 Home 键 ,有其它 APP 进入前台(比如接听电话) ,启动了新的Activity ,屏幕方向发生旋转 ,APP被杀死。

总之:系统只在 Acitivity 被异常终止的时候才会触发 onSaveInstanceStateonRestoreInstanceState

当系统配置变更,Activity 被销毁重建后的生命周期流程:

可以在 onSaveInstanceStateBundle 中保存数据,在 onRestoreInstanceState 中恢复数据。系统自动为我们做了一定的恢复工作。当 Activity 重建时,系统会为我们保存当前 Activity 的视图结构,并在 Activity 重启后恢复数据。

View视图数据恢复:

每个 View 都有 onSaveInstanceStateonRestoreInstanceState 方法。

Activity 被恶意终止时,Activity 会调用 onSaveInstanceState 去保存数据,然后 Activity 会委托 Window 去保存数据,接着 Window 再委托它上面的顶级容器去保存数据,通常顶级容器是一个 ViewGroup,一般来说很可能是 DecorVew。最后底层容器再去一一通知它的子View来保存数据,即调用 ViewGroupdispatchSaveInstanceState() 最终调用具体的View 的 onSaveInstanceState 去保存数据。

注意:View的数据恢复必须要在当前xml中为其设置 ID,否则是无法恢复的。

具体保存的数据可以看View子类的具体实现。

Activity中的状态保存与恢复

2.资源内存不足导致Activty被杀死

Acitivty的优先级:

1.前台 Activity,正在与用户交互,优先级最高。

2.可见但非前台,比如弹窗,透明Activity启动。

3.后台Activity,已经被暂停的 Activity,优先级最低。

后台工作不适合脱离四大组件而独立运行,这样的进程很容易被杀死,可以提供进程的优先级来降低被杀死的风险。

3.如何避免 Activity 重建

AndroidManifest 中为 Activity 配置 configChanges 配置来避免因配置变更导致 Acitivty 被销毁重建。

这样只会走 Activity 的 onConfigurationChanged 方法。

android:configChanges="screenSize|orientation|keyboardHidden|screenLayout" 

2.Activity的启动模式

1.LaunchMode

standard:标准模式

系统默认的模式,每次启动一个 Activity 都会重新创建一个新的实例,不管这个实例是否存在。一个任务栈可以有多个该 Activity 的实例,每个实例也可以在不同的任务栈。

在该模式下,谁启动了该 Acitivty,当前 Activity 就运行在启动它的那个 Activity 的任务栈中。

注意:在 standard 模式下,如果通过 ApplicationContext 去启动 Activity,会报异常,因为 ApplicationContext 启动的 Activity 没有所谓的任务栈。解决方法是为待启动的 Activity 指定 FLAG_ACTIVITY_NEW_TASK 标记位,这样启动的时候就会为它创建一个新的任务栈,这个时候待启动的 Activity 实际是以 singleTask 模式启动的。

应用场景: 大多数 Activity 适用的场景。

singleTop:栈顶复用模式

如果要新创建的 Activity 已经位于任务栈的栈顶,那么次 Activity 不会被重新创建,同时它的 onNewIntent 方法会被调用,对应的 onCreateonStart 方法不会被调用。

如果新创建的 Activity 实例已存在,但不位于栈顶,那么新 Activity 仍然会被重新创建。

应用场景:通知栏点击收到的通知,需要启动一个Activity,就可以用singleTop,否则每次点击都会新建一个Activity


singleTask:栈内复用模式

一种单例模式,只要 Activity 在一个栈中存在,那么多次启动此 Activity 都不会重新创建实例,系统会调用其 onNewIntent 方法。当启动一个模式为 singleTaskAcitivity A 的时候,系统首先寻找是否有 A 想要的任务栈,如果不存在,则重启创建一个任务栈,将 A 放进去。如果存在该任务栈,检查该任务栈中是否有 A 的实例,如果没有,创建放入。如果存在A的实例,则系统会把 A 上方的其他 Activity 移除,让 A 位于栈顶,并调用 onNewIntent 方法。

应用场景 :大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。

通过命令查看Activity任务栈情况adb shell dumpsys activity

场景一:A->B->C,B为 singleTask 模式,当前任务栈如下:


在【A,B,C】 中启动 B,任务栈如下:



场景二: 当前任务栈为:A->B->C,接着以 singTask + taskAffinity = “com.ubtech.taskS2” 启动 ActivityD



直接按Back键回退情况:

D -> C -> B -> A -> 桌面

查看手机的后台任务窗口如下

1.此时如果打开任务栈S2,则回退栈变为: D -> 桌面

2.此时如果打开任务栈S1,则回退栈变为:C->B->A->桌面

Uniapp开发遇到问题

uniapp 的主Activity的任务栈名称居然是打包的应用唯一标识码

singleInstance:单实例模式

加强的 singleTask,具有此模式的 Activity 只能单独的位于一个任务栈中,整个系统只有一个实例。

**应用场景:**系统界面,如来电界面等。


TaskAffinity
  • 该参数标识了一个 Activity 所需要的任务栈的名称,默认情况下,所有的 Activity 的任务栈的名字都为应用的包名。
  • 任务栈分为前台任务栈,后台任务栈,可以将后台任务栈切换到前台。

2.Activity 中 Flags 含义

FLAG_ACTIVITY_NEW_TASK

  • 这个标记位的作用就是为 Activity 指定 “singleTask” 模式,效果和在 xml 中指定该模式相同

FLAT_ACTIVITY_SINGLE_TOP

  • 这个标记位的作用就是为 Activity 指定 “singleTop” 模式,效果和在 xml 中指定该模式相同

FLAG_ACTIVITY_CLEAR_TOP

  • 具有此标记位的 Activity,当它启动时,在同一个任务栈中所有位于它上面的 Activity 都要出栈,需要和 FLAG_ACTIVITY_NEW_TASK配合使用,如果实例存在,会调用 onNewIntent 方法。

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

  • 具有此标记位的 Activity 不会出现在历史 Acitivity 的列表中,如果不希望用户通过历史列表回到该 Activity的时候使用该标记位置,等同于在 xml 中指定 android:excludeFromRecents=“true”。不等同于回退栈中没有它。

3. IntentFilter匹配规则

1.显示/隐式调用

1.显示调用
//1.显示调用方式一
Intent intent1 = new Intent(this,ActivityB.class);
startActivity(intent1);

//2.显示调用方式二
ComponentName component = new ComponentName(this,ActivityB.class);
Intent intent2 = new Intent();
intent2.setComponent(component);
startActivity(intent2);

//3.显示调用方式三
Intent intent3 = new Intent();
intent3.setClass(this,ActivityB.class);
startActivity(intent3); 

2.隐式调用

注意:必须在添加默认的

2.匹配规则

  • IntentFilter 中的过滤信息有 action,category,data。
  • 一个 IntentFilter 可以有多个 action,category,data。同一类别的信息共同约束当前类别的匹配过程。只有一个 Intent 同时匹配 action类别,category类别,data类别才算完全匹配。
  • 一个 Activity 可以有多个 IntentFilter,一个 Intent 只要能匹配任何一组 intent-filter 即可。
1. action匹配规则

Intent 中的 action 必须能后和 intent-filter 中的 action 匹配,一个 intent-filter 中有多个 action,Intent 中的 action 只要和其中的一个匹配就可。如果 Intent 中没有指定 action,则匹配失败。action 区分大小写。

2.category匹配规则

  • Intent 中如果有 category,所有的 category 都必须和 intent-filter 中的其中一个匹配,如果 Intent 中 出现的 category 必须是 intent-filter 中已经定义的。
  • Intent可以没有 category,仍可以匹配成功。系统在调用 startActivity 时候默认会为 Intent 添加 "android.intent.category.DEFAULT" 这个 category
  • 为了 activity 能够接受隐式调用,必须在 intent-filter 中指定 "android.intent.category.DEFAULT" 这个 category

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 为了 activity 能够接受隐式调用,必须在 intent-filter 中指定 "android.intent.category.DEFAULT" 这个 category

[外链图片转存中…(img-mG9KyyU8-1715723316740)]
[外链图片转存中…(img-oylEJlRm-1715723316741)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 30
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值