Activity 生命周期
Activity 是Android 四大组件之一,也是日常开发过程中最最常用的组件了。
Activity生命周期的7个方法说明:
onCreate()
, onStart()
, onResume()
, onPause()
, onStop()
, onRestart()
, onDestory()
方法名称 | 描述 | 用途举例 | 下一方法 |
---|---|---|---|
onCreate() | 当Activity第一次创建时调用。该方法(如果有)会提供给你一个包含之前 活动的冻结状态信息bundle. |
进行一系列初始化的操作时。例如:创建View,加载视频数据等等。 | onStart() |
onRestart() | 当Activity 状态为onStop()重新唤起后调用的方法 | 当活动停止后重新启动该活动时调用(不常用),针对停止后重启操作。 | onStart() |
onStart() | 该方法代表Activity正在被启动,此时Activity已经可见,但是此时Activity还未到前台,因此用户还无法看到,无法响应用户的交互互动作。 | - | onResume() |
onResume() | 当Activity将开始与用户进行交互时调用。在这个时间点你的活动将会在活动堆栈的顶端,用户输入将会访问它。 | 暂停后恢复我们会在该方法中进行一些操作,例如视频继续播放 | onPause() |
onPause() | onPause方法表示Activity正在暂停,正常情况下,onStop紧接着就会被调用。 | 该方法十分重要,用来做信息持久化存储操作以及停止消耗CPU资源操作,如记录视频播放进度时间,以及暂停视频播放操作等。 | onStop()或onResume() |
onStop() | 表示Activity即将停止,可以做一些稍微重量级的资源回收工作等,同样也不能太耗时。 | 界面将会隐藏或销毁,做一些重要信息或未被存储的信息的存储操作。但也不要太耗时。如存储用户信息等操作,以及用户此次观看的视频地址以及时间,便于下次打开该界面时继续播放。 | onDestory或onRestart() |
onDestory() | Activity被销毁钱最后一个被调用的方法。这个方法将会发生因为活动将会结束(在活动中调用finish()方法,或者系统临时销毁该实例节约空间。你可以使用isFinishing()方法区别这两种场景)。 | 界面将要销毁,释放一些实例节约空间,如置空List集合等。 | - |
Activity 阶段状态:
一个Activity 从本质上讲拥有4种状态:
- 运行:如果当前Activity 在前台界面(堆栈栈顶)
- 暂停:当ActivityA 被另一个非全屏ActivityB(如一个对话框) 覆盖时,ActivityA将会暂停,一个暂停的Activity也是可以货源的(他的成员和成员信息将会保留),当在内存资源缺乏时将会被系统回收。
- 停止: 当ActivityA 被另一个全屏ActivityB 覆盖时,那么ActivityA将处于停止状态,该活动也仍保留全部的状态和成员信息,但将会被隐藏起来不再展示给用户,并且当内存在其他地方被需要时该活动就将会被系统杀死。
- killed:这个activity已经被销毁,其所有的状态信息和成员变量已经不存在了。
状态转换:
# Activity 启动模式:
名称 | 描述 |
---|---|
standard | 标准模式 |
singleTop | 栈顶复用 |
singleTask | 任务栈单例 |
singleInstance | 单任务栈模式 |
四种模式详解:
standard:
标准模式,每次启动一个Activity 都会创建一个实例。
singleTop:
栈顶复用模式,即start的Activity 已经在栈顶的话,就会直接复用实例,此时在Intent 中传递的数据会在onNewIntent 方法中回调。如果目标Activity 不在栈顶,那么将创建一个新的实例。举例:一般的推送消息详情:收到推送通知时,用户点击消息后打开的Activity 会设置为singleTop 模式,方便复用。
singleTask:
任务栈单例模式,一个任务栈中只会存在一个这样的实例。当start 目标实例时候,不存在该实例则创建一个新的实例,如果存在,则会移除该实例上面的所有实例,将该实例处于栈顶,且回调onNewIntent 方法。举例:少数情况下销毁Activity :设置MainActivity 为singleTask 模式,当重新启动时候,他会销毁在他之前的所有Activity实例。
singleInstance:
单任务栈模式,该Activity 独享一个Activity 栈,且只有一个实例。如果已经启动该实例,再次启动将会调用onNewIntent 方法。
两个Activity之间跳转必然会执行的是哪几个方法:
-
一般情况比如说有两个activity,分别叫A、B ,当在A里面激活B组件的时候,A 会调用 onPause()方法,然后B 调用onCreate、onStart、 OnResume,这个时候B覆盖了窗体,A会调用onStop方法. 。
-
如果B是个透明的界面,或者是对话框的样式,,就不会调用onStop方法。
横竖屏切换的生命周期变化
这个生命周期跟清单文件里的配置有关系:
-
不设置Activity的android:configChanges时,切屏会销毁当前Activity,然后重新加载,重新调用各个生命周期。onPause —> onStop —> onDestory —> onCreate —>onStart —> onResume。
-
设置Activity的
android:configChanges="orientation|keyboardHidden|screenSize"
时,切屏不会重新调用各个生命周期,只会执行 onConfigurationChanged 方法。
Android 进程优先级
** 前台进程:Foreground process **
- 用户正在交互的Activity
- 当某个Service 绑定正在交互的Activity
- 被主动调用为前台的service(startForeground())
- 组件正在执行生命周期的回调(onCreate(), onStart(), onDestory())
- BroadcastReceier 正在执行onReceive()
可见进程:Visible process
- Activity 处于onPause()(没有进入onStop())
- 绑定到前台Activity 的service
服务进程:Service process
- 简单的startService()启动
后台进程:Background process
- 对用户没有直接影响的进程 — Activity 处于onStop() 的时候,android:process = ”:xxx“
空进程:Empty process
- 不含有任何的活动的组件。(Android设计的,处于缓存的目的,为了第二次启动更快,采取的一个权衡)
App 的入口
Android 是基于Java 语言的,而Java 有main()方法,那么Android 的主入口在哪里?
答案:有main()方法,main()方法在ActivityThread 类中的第6041行main(String[] args)
Scheme 跳转协议
Scheme是一种页面内跳转协议,是一种非常好的实现机制,通过定义自己的Scheme 协议,可以方便的跳转到app 的各个页面;
通过Scheme 协议,服务于可以定制化地告诉app应该换到哪个页面,可以从通知栏或H5 页面跳转到其他页面。
扩展补充:
后台的Activity 由于某种原因被系统回收了,如何在被系统回收前保存当前状态?
除了在栈顶的Activity ,其他的Activity 都有可能在内存不足时被系统回收掉,一个Activity 越处于栈底,被回收的可能性就越大;
一般情况下,调用onPause() 和onStop() 方法之后的Activity 实例仍然存在内存中,Activity 的所有信息和状态数据都不会消失,当Activity 重新回到前台之后,所有的改变都会得到保留。但当系统内存不足时,调用onPause() 和onStop() 方法后的Activity 可能会被系统销毁,此时内存中就不存在该Activity 的实例了,如果这个时候Activity 重新回到前台,之前所作的改变就会消失;
为了避免以上情况,我们可以覆写onSaveInstanceState()
方法。onSaveInstanceState() 方法接收一个Bundle 类型的参数,将需要保存的数据存储在这个Bundle 对象中,这样即使Activity 被系统销毁,当用户重新启动这个Activity 而调用它的onCreate() 方法时,上述的Bundle 对象会被作为实参传递给onCreate() 方法,这时可以从Bundle 中取出保存的数据,然后利用这些数据将Activity 恢复到被销毁之前的状态;
但是有些情况下,上述方式并不能完美解决该问题,例如正在播放视频时,手机突然没电或其他意外情况导致关机,这时想要在重新开机打开app后恢复之前的状态,我们可以每隔一段时间将所需数据保存在手机本地(数据库或者文件),等下次重新打开时,读取本地文件恢复之前播放的进度即可。