1 Activity状态
Activity 基本上以三种状态存在:
继续:此Activity位于屏幕前台并具有用户焦点。(有时也将此状态称作“运行中”。)
暂停:另一个Activity 位于屏幕前台并具有用户焦点,但此Activity 仍可见。但在内存极度不足的情况下,可能会被系统终止。
停止:该 Activity 被另一个Activity 完全遮盖(该 Activity 目前位于“后台”)。在他处需要内存时可能会被系统终止。
2 Activity生命周期回调方法:
其中,您必须在onCreate()方法内调用 setContentView(),以定义 Activity 用户界面的布局。
在销毁Activity之前,系统可能会先调用onSaveInstanceState(),但并无法保证系统一定会调用,因为存在不需要保存状态的情况(例如用户使用“返回”按钮离开您的 Activity 时,因为用户的行为是在显式关闭 Activity)。如果系统调用 onSaveInstanceState(),它会在调用onStop()之前,并且可能会在调用onPause()之前进行调用。
您可以在onSaveInstanceState()中使用 putString() 和 putInt() 等方法以名称-值对形式保存有关 Activity 状态的信息。之后,系统再次创建该Activity时,会将Bundle同时传递给onCreate()和 onRestoreInstanceState()以恢复状态。如果没有状态信息需要恢复,则传递的 Bundle是空值。
即使您不实现 onSaveInstanceState(),Activity类的onSaveInstanceState() 默认实现也会恢复部分 Activity 状态。默认实现会为布局中的每个 View 调用相应的 onSaveInstanceState() 方法,让每个视图都能提供有关自身的应保存信息,以便在重建 Activity 时自动保存和恢复对UI所做的任何可见更改。3 Activity生命周期
Activity生命周期举例
(1)Activity A启动Activity B时:先执行Activity A的onPause()方法,再执行Activity B的onCreate()、onStart()和onResume()方法,最后,如果此时Activity A不可见,则执行Activity A的onStop()方法。
(2)屏幕方向发生改变时,默认下系统调用 onDestroy(),然后立即调用 onCreate();
事实上,当Activity正在运行时,如果设备配置发生变化(例如屏幕方向、键盘可用性及语言),Android会重启正在运行的 Activity(先后调用 onDestroy() 和 onCreate())。重启行为旨在通过利用与新设备配置匹配的备用资源自动重新加载您的应用,来帮助它适应新配置。
tips:禁止屏幕旋转的方法,在manifest中<Activity>中指定screenOrientation属性。
4 运行时配置变更
当配置变化时,如果重启应用并恢复大量数据代价太大,而且给用户留下糟糕的使用体验。此时,您有两个其他选择:
(1) 在配置变更期间保留对象
onSaveInstanceState()并不是设计用于携带大型对象(例如位图),方法中的数据必须先序列化,再进行反序列化,这可能会消耗大量内存并使得配置变更速度缓慢。可通过保留Fragment来减轻重新初始化Activity 的负担。当Android系统因配置变更而关闭Activity时,不会销毁您已标记为要保留的 Activity 的fragment片段。
要在运行时配置变更期间将有状态的对象保留在片段中,请执行以下操作:
(1)扩展Fragment 类并声明对有状态对象的引用;
(2)在创建片段后调用fragment的方法setRetainInstance(boolean);
(3)将片段添加到 Activity;
(4)重启Activity后,使用FragmentManager检索片段;
标记为保留的fragment的生命周期将发生轻微改变:
销毁Activity时,onDestroy()不会被调用,
重启Activity时,onCreate()不会被调用
注意:切勿传递与 Activity 绑定的对象到该fragment,否则可能造成内存泄露。
(2) 自行处理配置变更:可阻止系统在某些配置变更期间重启Activity
要声明由 Activity 处理配置变更,请在清单文件中编辑相应的 <activity> 元素,以包含 android:configChanges 属性以及代表要处理的配置的值(最常用的值包括 "orientation" 和"keyboardHidden",分别对应屏幕方向改变和可用键盘改变)。当其中一个配置发生变化时,MyActivity不会重启。相反,MyActivity 会收到对onConfigurationChanged()的调用。您可以通过读取向此方法传递的Configuration中的字段,确定新配置,然后更新界面中使用的资源进行适当的更改。
5 任务和返回栈
任务是指在执行特定作业时与用户交互的一系列Activity。这些Activity按照各自的打开顺序排列在堆栈(即返回栈)中。
后台可以同时运行多个任务。但是,如果用户同时运行多个后台任务,则系统可能会开始销毁后台 Activity,以回收内存资源,从而导致Activity 状态丢失(通过实现onSaveInstanceState()来保留工作)。
如果用户长时间离开任务,则系统会清除所有 Activity 的任务,根 Activity 除外。当用户再次返回到任务时,仅恢复根 Activity。
6 定义任务和Activity的行为
通过使用<activity> 清单文件元素中的属性和传递给 startActivity() 的 Intent 中的标志,您可以定义任务和Activity的行为。
<activity> 属性包括:
taskAffinity:处理关联,指定该Activity优先属于哪个任务;
launchMode:启动模式;
allowTaskReparenting:设置为”true”时,Activity 可以从其启动的任务移动到与其具有关联的任务(如果该任务出现在前台);
clearTaskOnLaunch:如果在任务的根Activity 中将此属性设置为 "true",则每当用户离开任务然后返回时,系统都会将堆栈清除到只剩下根 Activity;
alwaysRetainTaskState:如果在任务的根Activity 中将此属性设置为 "true",则即使在很长一段时间后,任务仍将所有 Activity 保留在其堆栈中;
finishOnTaskLaunch:此属性类似于clearTaskOnLaunch,但它对单个Activity起作用,而非整个任务。设置为 "true" 时,Activity仍是任务的一部分,但是仅限于当前会话。如果用户离开然后返回任务,则任务将不复存在;
Intent 标志:包括FLAG_ACTIVITY_NEW_TASK、FLAG_ACTIVITY_CLEAR_TOP、FLAG_ACTIVITY_SINGLE_TOP,全用于定义Activity的启动模式。
7 启动模式
"standard"(默认模式)
默认。系统在启动该Activity的任务中创建该Activity的新实例并向其传送 Intent。Activity可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。
"singleTop"
如果当前任务的顶部已存在该Activity 的一个实例,则系统会通过调用该实例的 onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。
如果当前任务的顶部不是该Activity的实例,则新建Activity的实例。
"singleTask"
系统创建新任务并实例化位于新任务底部的Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的 onNewIntent()方法向其传送Intent,而不是创建新实例。如果该顶部Activity已经是某个拥有自己的返回栈的后台任务的一部分,则整个返回栈也会上移到当前任务的顶部。
"singleInstance"
与 "singleTask" 相同,只是系统不会将任何其他Activity启动到包含实例的任务中。该Activity 始终是其任务唯一仅有的成员;由此Activity启动的任何 Activity均在单独的任务中打开。
Intent标志:
FLAG_ACTIVITY_NEW_TASK:等价于<activity>的launchmode属性"singleTask"
FLAG_ACTIVITY_SINGLE_TOP:等价于<activity>的launchmode属性"singleTop"
FLAG_ACTIVITY_CLEAR_TOP:如果正在启动的Activity 已在当前任务中运行,则会销毁当前任务顶部的所有 Activity,并通过 onNewIntent() 将此 Intent 传递给 Activity 已恢复的实例(现在位于顶部),而不是启动该 Activity 的新实例。
将Activity标记为"singleTask"和"singleInstance"启动模式时,该Activity应该具有ACTION_MAIN和CATEGORY_LAUNCHER过滤器。