Android---Activity

1、说下 Activity 生命周期 ?
在正常情况下,Activity 的常用生命周期就只有如下 7 个
1 ) onCreate():表示 Activity 正在被创建,常用来初始化工作,比如调用 setContentView 加载界面布局资源,初始化 Activity 所需数据等;
2 ) onRestart():表示 Activity 正在重新启动,一般情况下,当前Acitivty 从不可见重新变为可见时,OnRestart 就会被调用;
3 ) onStart():表示 Activity 正在被启动,此时 Activity 可见但不在前台,还处于后台,无法与用户交互;
4 ) onResume():表示 Activity 获得焦点,此时 Activity 可见且在前台并开始活动,这是与 onStart 的区别所在;
5 ) onPause():表示 Activity 正在停止,此时可做一些存储数据、停止动画等工作,但是不能太耗时,因为这会影响到新 Activity的显示,onPause 必须先执行完,新 Activity 的 onResume 才会执行;
6 ) onStop():表示 Activity 即将停止,可以做一些稍微重量级的回收工作,比如注销广播接收器、关闭网络连接等,同样不能太耗时;
7 ) onDestroy():表示 Activity 即将被销毁,这是 Activity 生命周期中的最后一个回调,常做回收工作、资源释放;

延伸:
从整个生命周期来看,onCreate 和 onDestroy 是配对的,分别标识着 Activity 的创建和销毁,并且只可能有一次调用; 从 Activity 是否可见来说,onStart 和 onStop 是配对的,这两个方法可能被调用多次; 从 Activity 是否在前台来说,onResume 和 onPause 是配对的,这两个方法可能被调用多次; 除了这种区别,在实际使用中没有其他明显区别;

2、Activity A 启动另一个 Activity B 会调用哪些方法?如果 B 是透明主题的又或则是个 DialogActivity 呢 ?
Activity A 启动另一个 Activity B,回调如下
1 ) Activity A 的 onPause() → Activity B 的 onCreate() →onStart() → onResume() →Activity A 的 onStop();
2 ) 如果 B 是透明主题又或则是个 DialogActivity,则不会回调 A 的onStop;

3、说下 onSaveInstanceState()方法的作用 ? 何时会被调用?
发生条件:异常情况下(系统配置发生改变时导致 Activity被杀死并重新创建、资源内存不足导致低优先级的 Activity 被杀死)
1 ) 系统会调用 onSaveInstanceState 来保存当前 Activity 的状态,此方法调用在 onStop 之前,与 onPause 没有既定的时序关系;
2 ) 当 Activity 被重建后,系统会调用 onRestoreInstanceState,并且把 onSave(简称)方法所保存的 Bundle 对象同时传参给onRestore(简称)和 onCreate(),因此可以通过这两个方法判断Activity 是否被重建,调用在 onStart 之后;

4、说下 Activity 的四种启动模式、应用场景 ?
1 ) standard 标准模式:每次启动一个 Activity 都会重新创建一个新的实例,不管这个实例是否已经存在,此模式的 Activity 默认会进入启动它的 Activity 所属的任务栈中;
2 ) singleTop 栈顶复用模式:如果新 Activity 已经位于任务栈的栈顶,那么此 Activity 不会被重新创建,同时会回调 onNewIntent方法,如果新 Activity 实例已经存在但不在栈顶,那么Activity 依然会被重新创建;也就是说,调用顺序如下:onNewIntent() -> onRestart() -> onStart() -> onResume()
3 ) singleTask 栈内复用模式:只要 Activity 在一个任务栈中存在,那么多次启动此 Activity 都不会重新创建实例,并回调onNewIntent 方法,此模式启动 Activity A,系统首先会寻找是否存在 A 想要的任务栈,如果不存在,就会重新创建一个任务栈,然后把创建好 A 的实例放到栈中;
4 ) singleInstance 单实例模式:这是一种加强的 singleTask 模式,具有此种模式的Activity 只能单独地位于一个任务栈中,且此任务栈中只有唯一一个实例;

5、了解哪些 Activity 常用的标记位 Flags?
1 ) FLAG_ACTIVITY_NEW_TASK : 对应 singleTask 启动模式,其效果和在 XML 中指定该启动模式相同;
2 ) FLAG_ACTIVITY_SINGLE_TOP : 对应 singleTop 启动模式,其效果和在 XML 中指定该启动模式相同;
3)FLAG_ACTIVITY_CLEAR_TOP : 具有此标记位的 Activity,当它启动时,在同一个任务栈中所有位于它上面的 Activity 都要出栈。这个标记位一般会和 singleTask 模式一起出现,在这种情况下,被启动 Activity 的实例如果已经存在,那么系统就会回调onNewIntent。如果被启动的 Activity 采用 standard 模式启动,那么它以及连同它之上的 Activity 都要出栈,系统会创建新的Activity 实例并放入栈中;
4)FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS : 具有这个标记的Activity 不会出现在历史 Activity 列表中;

6、说下 Activity 跟 window,view 之间的关系?
Activity 创建时通过 attach()初始化了一个 Window 也就是PhoneWindow,一个 PhoneWindow 持有一个 DecorView 的实例,DecorView 本身是一个 FrameLayout,继承于 View,Activty 通过setContentView 将 xml 布局控件不断 addView()添加到 View 中,最终显示到 Window 于我们交互;

7、横竖屏切换的 Activity 生命周期变化?
1)不设置 Activity 的 android:configChanges 时,切屏会销毁当前Activity,然后重新加载调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次; onPause()→onStop()→onDestory()→onCreate()→onStart()→onResume()
2)设置 Activity 的 android:configChanges=“orientation”,经过机型测试
a. 在 Android5.1 即 API 23 级别下,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
b. 在 Android9 即 API 28 级别下,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged 方法

官方纠正后,原话如下
如果您的应用面向 Android 3.2 即 API 级别 13 或更高级别(按照 minSdkVersion 和 targetSdkVersion属性所声明的级别),则还应声明 “screenSize” 配置,因为当设备在横向与纵向之间切换时,该配置也会发生变化。即便是在 Android 3.2 或更高版本的设备上运行,此配置变更也不会重新启动Activity
设置 Activity 的android:configChanges="orientation|keyboardHidden|screenSize"时,机型测试通过,切屏不会重新调用各个生命周期,只会执行 onConfigurationChanged 方法;

8、如何启动其他应用的 Activity?
在保证有权限访问的情况下,通过隐式 Intent 进行目标Activity 的 IntentFilter 匹配,原则是:
一个 intent 只有同时匹配某个 Activity 的 intentfilter 中的 action、category、data 才算完全匹配,才能启动该 Activity;
一个 Activity 可以有多个 intent-filter,一个 intent只要成功匹配任意一组 intent-filter,就可以启动该Activity;

9、Activity 的启动过程?(重点)
Activity启动流程(从Launcher开始):

1)第一阶段: Launcher通知AMS要启动新的Activity(在Launcher所在的进程执行)

Launcher.startActivitySafely //首先Launcher发起启动Activity的请求
Activity.startActivity
Activity.startActivityForResult
Instrumentation.execStartActivity //交由Instrumentation代为发起请求
ActivityManager.getService().startActivity //通过IActivityManagerSingleton.get()得到一个AMP代理对象
ActivityManagerProxy.startActivity //通过AMP代理通知AMS启动activity
2)第二阶段:AMS先校验一下Activity的正确性,如果正确的话,会暂存一下Activity的信息。然后,AMS会通知Launcher程序pause Activity(在AMS所在进程执行)

ActivityManagerService.startActivity
ActivityManagerService.startActivityAsUser
ActivityStackSupervisor.startActivityMayWait
ActivityStackSupervisor.startActivityLocked :检查有没有在AndroidManifest中注册
ActivityStackSupervisor.startActivityUncheckedLocked
ActivityStack.startActivityLocked :判断是否需要创建一个新的任务来启动Activity。
ActivityStack.resumeTopActivityLocked :获取栈顶的activity,并通知Launcher应该pause掉这个Activity以便启动新的activity。
ActivityStack.startPausingLocked
ApplicationThreadProxy.schedulePauseActivity
3)第三阶段: pause Launcher的Activity,并通知AMS已经paused(在Launcher所在进程执行)

ApplicationThread.schedulePauseActivity
ActivityThread.queueOrSendMessage
H.handleMessage
ActivityThread.handlePauseActivity
ActivityManagerProxy.activityPaused
4)第四阶段:检查activity所在进程是否存在,如果存在,就直接通知这个进程,在该进程中启动Activity;不存在的话,会调用Process.start创建一个新进程(执行在AMS进程)

ActivityManagerService.activityPaused
ActivityStack.activityPaused
ActivityStack.completePauseLocked
ActivityStack.resumeTopActivityLocked
ActivityStack.startSpecificActivityLocked
ActivityManagerService.startProcessLocked
Process.start //在这里创建了新进程,新的进程会导入ActivityThread类,并执行它的main函数
5)第五阶段: 创建ActivityThread实例,执行一些初始化操作,并绑定Application。如果Application不存在,会调用LoadedApk.makeApplication创建一个新的Application对象。之后进入Loop循环。(执行在新创建的app进程)

ActivityThread.main
ActivityThread.attach(false) //声明不是系统进程
ActivityManagerProxy.attachApplication
6)第六阶段:处理新的应用进程发出的创建进程完成的通信请求,并通知新应用程序进程启动目标Activity组件(执行在AMS进程)

ActivityManagerService.attachApplication //AMS绑定本地ApplicationThread对象,后续通过ApplicationThreadProxy来通信。
ActivityManagerService.attachApplicationLocked
ActivityStack.realStartActivityLocked //真正要启动Activity了!
ApplicationThreadProxy.scheduleLaunchActivity //AMS通过ATP通知app进程启动Activity
第七阶段: 加载MainActivity类,调用onCreate声明周期方法(执行在新启动的app进程)

ApplicationThread.scheduleLaunchActivity //ApplicationThread发消息给AT
ActivityThread.queueOrSendMessage
H.handleMessage //AT的Handler来处理接收到的LAUNCH_ACTIVITY的消息
ActivityThread.handleLaunchActivity
ActivityThread.performLaunchActivity
Instrumentation.newActivity //调用Instrumentation类来新建一个Activity对象
Instrumentation.callActivityOnCreate
MainActivity.onCreate
ActivityThread.handleResumeActivity
AMP.activityResumed
AMS.activityResumed(AMS进程)

10、onRestart 的调用场景
1)按下 home 键之后,然后切换回来,会调用 onRestart();
2)从本 Activity 跳转到另一个 Activity 之后,按 back 键返回原来 Activity,会 调用 onRestart();
3)从本 Activity 切换到其他的应用,然后再从其他应用切换回来,会调用 onRestart();

11、android 重要术语解释
1)ActivityManagerServices,简称 AMS,服务端对象,负责系统中所有Activity 的生命周期
2)ActivityThread,App 的真正入口。当开启App 之后,会调用 main()开始运行,开启消息循环队列,这就是传说中的 UI 线程或者叫主线程。与 ActivityManagerServices 配合,一起完成 Activity 的管理工作
3)ApplicationThread , 用 来 实 现 ActivityManagerService 与 ActivityThread 之 间 的 交 互 。 在ActivityManagerService 需 要 管 理 相 关 Application 中 的 Activity 的 生 命 周 期 时 , 通 过ApplicationThread 的代理对象与 ActivityThread 通讯。
4)ApplicationThreadProxy , 是 ApplicationThread 在 服 务 器 端 的 代 理 , 负 责 和 客 户 端 的ApplicationThread 通讯。AMS 就是通过该代理与 ActivityThread 进行通信的。
5)Instrumentation,每一个应用程序只有一个 Instrumentation 对象,每个 Activity 内都有一个对该对象的引用。Instrumentation 可以理解为应用进程的管家,ActivityThread 要创建或暂停某个Activity时,都需要通过 Instrumentation 来进行具体的操作。
6)ActivityStack,Activity 在AMS 的栈管理,用来记录已经启动的 Activity 的先后关系,状态信息等。通过 ActivityStack 决定是否需要启动新的进程。
7)ActivityRecord,ActivityStack 的管理对象,每个 Activity 在 AMS 对应一个ActivityRecord,来记录 Activity 的状态以及其他的管理信息。其实就是服务器端的 Activity 对象的映像。
8)TaskRecord,AMS 抽象出来的一个“任务”的概念,是记录 ActivityRecord 的栈,一个“Task”包含若干个 ActivityRecord。AMS 用 TaskRecord 确保 Activity 启动和退出的顺序。如果你清楚 Activity 的 4 种 launchMode,那么对这个概念应该不陌生。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值