安卓中activity的生命周期_Android生命周期

(78) 2024-07-03 21:01:01

目录

Activity 简介

Activity 生命周期概念

onCreate()

onStart()

onResume()

onPouse()

onStop()

onDestory()

onRestart()

Activity 生命周期超时设定 

保存和恢复瞬时界面状态

onSaveInstanceState()使用

在 Activity 之间导航

多窗口支持

Framework启动activity 流程

一般流程

framework通知activity生命周期-ActivityLifecycleItem

类图

流程图

参考文档



Activity 简介

  Activity 类是 Android 应用的关键组件,Activity 充当了应用与用户互动的入口点。通常,一个 Activity 实现应用中的一个界面。

Activity 生命周期概念

    当用户浏览、退出和返回应用时,应用中的 Activity 实例会在其生命周期的不同状态间转换。Activity 类会提供许多回调,这些回调会让 Activity 知晓某个状态已经更改:系统正在创建、停止或恢复某个 Activity,或者正在销毁该 Activity 所在的进程。使用这些回调Activity可以在适当的时机做相应的工作。

    Activity 类提供六个核心回调:onCreate()onStart()onResume()onPause()onStop() 和 onDestroy()

安卓中activity的生命周期_Android生命周期 (https://mushiming.com/)  第1张

  上面图概括了android生命周期的各个环节,描述了activity从生成到销毁的过程。

onCreate()

    当我们点击activity的时候,系统会调用activity的oncreate()方法,activity必须实现此回调,在这个方法中我们会使用setContentView() 来指定 XML 布局文件。 它会在系统首次创建 Activity 时触发。Activity 会在创建后进入“已创建”状态。在 onCreate() 方法中,需执行基本应用启动逻辑,该逻辑在 Activity 的整个生命周期中只应发生一次。例如,将数据绑定到列表, 实例化某些类变量。此方法会接收 savedInstanceState 参数,后者是包含 Activity 先前保存状态的 Bundle 对象。如果 Activity 此前未曾存在,Bundle 对象的值为 null。

onStart()

    onCreate()方法完成后,此时activity进入onStart()方法,当前activity是用户可见状态,但没有焦点,与用户不能交互,一般可在当前方法做一些动画的初始化操作。

onResume()

    onStart()方法完成之后,此时activity进入onResume()方法中,当前activity状态属于运行状态 (Running),可与用户进行交互。activity 需要恢复在onPause 函数中释放掉的组件。

onPouse()

    当另外一个activity覆盖当前的acitivty时,此时当前activity会进入到onPouse()方法中,当前activity是可见的,但不能与用户交互状态。此方法表示 Activity 不再位于前台(尽管在用户处于多窗口模式时 Activity 仍然可见)。

    Activity 进入此状态的原因有很多。例如:

  • 如 onResume() 部分所述,某个事件会中断应用执行。这是最常见的情况。
  • 在 Android 7.0(API 级别 24)或更高版本中,有多个应用在多窗口模式下运行。无论何时,都只有一个应用(窗口)可以拥有焦点,因此系统会暂停所有其他应用。
  • 有新的半透明 Activity(例如对话框)处于开启状态。只要 Activity 仍然部分可见但并未处于焦点之中,它便会一直暂停

    如果处于多窗口模式,“已暂停”的 Activity 仍完全可见。因此,应该考虑使用 onStop() 而非 onPause() 来完全释放或调整与界面相关的资源和操作,以便更好地支持多窗口模式。

  onPause() 执行非常简单,而且不一定要有足够的时间来执行保存操作, 在AMS中pause time out 时间为500ms。因此,应使用 onPause() 来保存应用或用户数据、进行网络调用或执行数据库事务。因为在该方法完成之前,此类工作可能无法完成。相反,应在 onStop() 期间执行高负载的关闭操作。

onStop()

    onPouse()方法完成之后,此时activity进入onStop()方法,此时activity对用户是不可见的,在系统内存紧张的情况下,有可能会被系统进行回收。所以一般在当前方法可做资源回收。

    如果 Activity 已结束运行并即将终止,系统还可以调用 onStop()

    应用应释放或调整在应用对用户不可见时的无用资源。例如,应用可以暂停动画效果,或从精确位置更新切换到粗略位置更新。使用 onStop() 而非 onPause() 可确保与界面相关的工作继续进行,即使用户在多窗口模式下查看Activity 也能如此。

    还应使用 onStop() 执行 CPU 相对密集的关闭操作。例如,如果无法找到更合适的时机来将信息保存到数据库,可以在 onStop() 期间执行此操作。

    进入“已停止”状态后,Activity 要么返回与用户互动,要么结束运行并消失。如果 Activity 返回,系统将调用 onRestart()。如果 Activity 结束运行,系统将调用 onDestroy()

onDestory()

    销毁 Ativity 之前,系统会先调用 onDestroy()。系统调用此回调的原因如下:

  1. Activity 即将结束(由于用户彻底关闭 Activity 或由于系统为 Activity 调用 finish()),或者
  2. 由于配置变更(例如设备旋转或多窗口模式),系统暂时销毁 Activity

    如果 Activity 即将结束,onDestroy() 是 Activity 收到的最后一个生命周期回调。如果由于配置变更而调用 onDestroy(),系统会立即新建 Activity 实例,然后在新配置中为新实例调用 onCreate()。

    onDestroy() 回调应释放先前的回调(例如 onStop())尚未释放的所有资源。

    应使用 ViewModel 对象来包含 Activity 的相关视图数据,而不是在 Activity 中加入逻辑来确定 Activity 被销毁的原因。如果因配置变更而重新创建 Activity,ViewModel 不必执行任何操作,因为系统将保留 ViewModel 并将其提供给下一个 Activity 实例。如果不重新创建 Activity,ViewModel 将调用 onCleared() 方法,以便在 Activity 被销毁前清除所需的任何数据。

onRestart()

    onRestart()方法在用户按下home()之后,再次进入到当前activity的时候调用。调用顺序onPouse()->onStop()->onRestart()→onStart()→onResume().

Activity 生命周期超时设定 

    在ActiviteStack.java中我们可以看到生命周期的超时时间:

  • onPause是500毫秒
  • onStop和onDestory是10秒
/ How long we wait until giving up on the last activity to pause. This // is short because it directly impacts the responsiveness of starting the // next activity. private static final int PAUSE_TIMEOUT = 500; // How long we wait for the activity to tell us it has stopped before // giving up. This is a good amount of time because we really need this // from the application in order to get its saved state. private static final int STOP_TIMEOUT = 10 * 1000; // How long we wait until giving up on an activity telling us it has // finished destroying itself. private static final int DESTROY_TIMEOUT = 10 * 1000

保存和恢复瞬时界面状态

    某些情况用户希望当他们启动 Activity 时,该 Activity 的上次的界面状态会保持不变,直到用户完全关闭 Activity 为止。例如配置改变导致activity 重启、用户暂时切换到其他应用,稍后再返回到应用,他们也会希望 Activity 的界面状态保持不变。

当 Activity 因系统限制而被销毁时,可组合使用一下方法来保留用户的瞬时界面状态:

  • ViewModel, 参加后面参考文档。
  • onSaveInstanceState(): 要保留的是简单的轻量级界面数据,通过bundle键值对存储数据。
  • 本地存储。

onSaveInstanceState()使用

在activity再次启动时, 通过两种方法之一获得之前存储的bundle信息。

  1. 在onCreate中通过savedInstanceState参数传递回来,用于恢复相关信息。
  2. 实现onRestoreInstanceState()。 系统在 onStart() 方法之后调用 onRestoreInstanceState(),仅当存在要恢复的已保存状态时,系统才会调用 onRestoreInstanceState(),因此无需检查 Bundle 是否为 null。 

    当Activity 开始停止时,系统会调用 onSaveInstanceState() 方法,以便Activity 可以将状态信息保存到实例状态 Bundle 中。此方法的默认实现保存有关 Activity 视图层次结构状态的瞬时信息,例如 EditText 微件中的文本或 ListView 微件的滚动位置。

    如需保存 Activity 的其他实例状态信息,必须替换 onSaveInstanceState(),并将键值对添加到 Bundle 对象中。替换 onSaveInstanceState() 时,如果望默认实现保存视图层次结构的状态,必须调用父类实现。

    onSaveInstanceState方法调用注意事项 :
    用户主动销毁不会调用 : 当用户点击回退键 或者 调用了 finish() 方法, 不会调用该方法;
调用时机不固定 : 在Android Honeycomb,  onSaveInstanceState在  onPause前调用。

        Android P 之前, onSaveInstanceState在onStop()前调用。

        Android P及之后 onSaveInstanceState在onStop()后调用。

在 Activity 之间导航

从一个 Activity 启动另一个 Activity

使用以下方法启动activity:

1. startActivity() 启动新的activity, 并不需要新的activity 返回结果给当前activity。

2. startActivityForResult()启动新 Activity, 但需要新的activity 返回结果给当前activity。父activity 实现onActivityResult(int, int, Intent)。 子activity 需调用setResult(int) 将数据返回到其父级。

可使用adb logcat -b events 查看生命周期调用顺序

注1: 当AActivity切换BActivity的所执行的方法:

AActivity: onCreate()->onStart()->onResume()->onPouse()
BActivity: onCreate()->onStart()->onResume()
AActivity: onStop()    可能 →onDestory()

注2: 从BActivity 按back 退回AActivity:

BActivity:onPouse()
AActivity: onRestart() ->onStart()->onResume()
BActivity:onStop()   →onDestory()

注 3: 当AActivity切换BActivity(此activity是以dialog形式存在的)所执行的方法:

AActivity: onCreate()->onStart()->onResume()->onPouse()
BActivity: onCreate()→onStart()→onResume()

注 4: AActivity按power 灭屏

AActivity: onPause() → onStop()

keyguard show

注 5: keyguard 到AActivity:

keyguard go away

AActivity: onRestart()→ onStart()→onResume()

注 6: AActivity中下拉导航栏:

AActivity 失去焦点,依然resume状态

多窗口支持

Android 7.0 新增了对同时显示多个应用窗口的支持。分屏, 画中画, freeform。 

多窗口模式不会更改 activity 生命周期。

不同Android版本区别:

  • Android 9.0 及以前版本, 在多窗口模式下,在任意时间点都只有用户最近一次互动的 Activity 处于活动状态。此 Activity 被视为最顶层的 Activity,而且是唯一处于 RESUMED 状态的 Activity。所有其他可见的 Activity 均处于 Paused状态。但是某些app 在pause状态终止一些活动, 比如播放视频, 会导致问题。
  • Android10,  在多窗口模式下, 所有visible 并且facusable 的activity  均为resumed状态。如果一个activity 是不可focusable或者有一个透明的activity 在其上面, 这个activity 也可能是paused 状态。android 10提供新的回调函数Activity#onTopResumedActivityChanged()通知activty 得到或者失去top resumed activity.

Framework启动activity 流程

一般流程

以下仅为普遍流程, 不同情况下, 启动activity 流程略有不同, 比如温启动等。仅供参考。 call stack 为从下到上。 

1. 启动之前已经启动过,且没有被destroy的activity, 先resume target activity, 然后pause 当前activity:

startPausingLocked:1102, ActivityStack (com.android.server.wm)
pauseBackStacks:1201, TaskDisplayArea (com.android.server.wm)
resumeTopActivityInnerLocked:1658, ActivityStack (com.android.server.wm)
resumeTopActivityUncheckedLocked:1507, ActivityStack (com.android.server.wm)//返回true, 代表已经resumed activy
resumeFocusedStacksTopActivities:2362, RootWindowContainer (com.android.server.wm)
resumeTargetStackIfNeeded:2555, ActivityStarter (com.android.server.wm)
recycleTask:1947, ActivityStarter (com.android.server.wm)
startActivityInner:1634, ActivityStarter (com.android.server.wm)
startActivityUnchecked:1528, ActivityStarter (com.android.server.wm)
executeRequest:1187, ActivityStarter (com.android.server.wm)
execute:669, ActivityStarter (com.android.server.wm)
startActivityAsUser:1145, ActivityTaskManagerService (com.android.server.wm)
startActivityAsUser:1117, ActivityTaskManagerService (com.android.server.wm)
startActivity:1092, ActivityTaskManagerService (com.android.server.wm)
onTransact:1429, IActivityTaskManager$Stub (android.app)
execTransactInternal:1154, Binder (android.os)
execTransact:1123, Binder (android.os)

2. 启动新的activity

先创建activity process, paused 当前activity. 

startPausingLocked:1102, ActivityStack (com.android.server.wm) resumeTopActivityInnerLocked:1662, ActivityStack (com.android.server.wm) resumeTopActivityUncheckedLocked:1507, ActivityStack (com.android.server.wm) resumeFocusedStacksTopActivities:2362, RootWindowContainer (com.android.server.wm) startActivityInner:1739, ActivityStarter (com.android.server.wm) startActivityUnchecked:1528, ActivityStarter (com.android.server.wm) executeRequest:1187, ActivityStarter (com.android.server.wm) execute:669, ActivityStarter (com.android.server.wm) startActivityAsUser:1145, ActivityTaskManagerService (com.android.server.wm) startActivityAsUser:1117, ActivityTaskManagerService (com.android.server.wm) startActivity:1092, ActivityTaskManagerService (com.android.server.wm) onTransact:1429, IActivityTaskManager$Stub (android.app) execTransactInternal:1154, Binder (android.os) execTransact:1123, Binder (android.os)

然后在收到activityPaused后resume新的activity, activityPause:

realStartActivityLocked:721, ActivityStackSupervisor (com.android.server.wm) startSpecificActivity:982, ActivityStackSupervisor (com.android.server.wm) resumeTopActivityInnerLocked:1958, ActivityStack (com.android.server.wm) resumeTopActivityUncheckedLocked:1507, ActivityStack (com.android.server.wm) resumeFocusedStacksTopActivities:2362, RootWindowContainer (com.android.server.wm) completePauseLocked:1209, ActivityStack (com.android.server.wm) activityPaused:4973, ActivityRecord (com.android.server.wm) activityPaused:1890, ActivityTaskManagerService (com.android.server.wm) onTransact:1951, IActivityTaskManager$Stub (android.app) execTransactInternal:1154, Binder (android.os) execTransact:1123, Binder (android.os) 

framework通知activity生命周期-ActivityLifecycleItem

framework 通过activitylifecycleitem 发送activity 生命周期状态给activity,对应pause, resume 等生命周期, ActivityLifecycleItem 继承自ClientTransactionItem,这些activitylifecycleitem包括: 

StartActivityItem
StopActivityItem
DestroyActivityItem
ResumeActivityItem
PauseActivityItem

其他继承ClientTransactionItem的类: 
ConfigurationChangeItem
EnterPipRequestedItem
FixedRotationAdjustmentsItem
ActivityResultItem
ActivityConfigurationChangeItem
MoveToDisplayItem
NewIntentItem
TopResumedActivityChangeItem
ActivityRelaunchItem 
LaunchActivityItem

在framework中通过类似以下代码发送生命周期信息给app:

  final ActivityLifecycleItem lifecycleItem;  //创建ResumeActivityItem  lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());  //创建ClientTeansaction, 并设置lifecycleItem final ClientTransaction clientTransaction = ClientTransaction.obtain(                           proc.getThread(), r.appToken);                clientTransaction.setLifecycleStateRequest(lifecycleItem);  // Schedule transaction. mService.getLifecycleManager为ClientLifecycleManager  mService.getLifecycleManager().scheduleTransaction(clientTransaction); 了

类图

1. ClientTransaction持有IApplicationThread,为要通信的app端AIDL接口, 服务端通过该接口于app端通信。ClientTransaction持有对象mActivityCallbacks和mLifecycleStateRequest,这些均为ClientTransactionItem类型。 mActivityCallbacks为list, 可以有多个。 mLifecycleStateRequest只能有一个。

2.ClientTransactionItem子类具体描述要求app执行的生命周期状态或其他信息, 有多个子类。 其中ActivityLifecycleItem子类专门用来描述要求app执行的生命周期状态。 

3. ActivityThread继承ClientTransactionHandler, ClientTransactionItem调用该类执行相关功能, 如handleResumeActivity()。

安卓中activity的生命周期_Android生命周期 (https://mushiming.com/)  第2张

流程图

1.在service侧,首先会构建一个ClientTransaction对象, 通过addCallback()设置mActivityCallbacks和通过setLifecycleStateRequest()设置mLifecycleStateRequest。 其中mActivityCallbacks为list, 可以有多个。 mLifecycleStateRequest只能有一个, 二者均为ClientTransactionItem子类。 

2. ams 和wms在适当时机通过在ClientLifecycleManager.scheduleTransaction将上一步创建的ClientTransaction传递给app, 通知app生命周期状态或者其他信息变化

2.在app 的ActivityThread中接收到这些变化后, 先调用ClientTransaction的mActivityCallbacks的preExecute后调用mLifecycleStateRequest的preExecute()设置一些提前工作。这些均为ClientTransactionItem子类, 每个子类的执行不同,包括后面的execute()和postEcexute()各子类有不同实现。 调用顺序也为先mActivityCallbacks后mLifecycleStateRequest。  如在ConfigurationChangeItem中预置configuration,在 DestroyActivityItem中添加destroyactivity到ActivityThread的mActivitiesToBeDestroyed列表。调用顺序为先调用mActivityCallbacks的preExecute后调用mLifecycleStateRequest的preExecute(). 

3.在app 端调用ClientTransactionItem子类的execute() 执行状态或其他信息变化. 比如调用到activity.onResume等函数。 

4.在app 端调用ClientTransactionItem子类的postEcexute()通知service, 一般为ActivityTaskManager执行了相关操作,如activityPaused(),  从而在services端继续执行相应操作, 并去掉系统的timeout .

安卓中activity的生命周期_Android生命周期 (https://mushiming.com/)  第3张

参考文档

  • 了解 Activity 生命周期: 

https://developer.android.com/guide/components/activities/activity-lifecycle

  • ViewModel: https://developer.android.com/reference/androidx/lifecycle/ViewModel
  • multi-resumed: https://developer.android.com/guide/topics/ui/foldables#multi-resume
  •  Lifecycle: https://developer.android.com/reference/androidx/lifecycle/Lifecycle
  • Activity事务管理讲解(ClientLifecycleManager)_execute_transaction-CSDN博客
THE END

发表回复