一、Activity的生命周期
1、什么是Activity
Activity是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器)之一
Activity中所有操作都与用户密切相关,是一个负责与用户交互的组件,可以通过setContentView(View)来显示指定控件。
在一个android应用中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity之间通过Intent进行通信。2、Activity的四种状态
1、running
一个新 Activity 启动入栈后,它显示在屏幕最前端,处于栈的最顶端(Activity栈顶),此时它处于可见并可和用户交互的激活状态,叫做活动状态或者运行状态(active or running)。
2、pause
当 Activity失去焦点, 被一个新的非全屏的Activity 或者一个透明的Activity 被放置在栈顶,此时的状态叫做暂停状态(Paused)。此时它依然与窗口管理器保持连接,Activity依然保持活力(保持所有的状态,成员信息,和窗口管理器保持连接),但是在系统内存极端低下的时候将被强行终止掉。所以它仍然可见,但已经失去了焦点故不可与用户进行交互。
3、stoped
如果一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被强行终止掉。
4、killed
如果一个Activity是Paused或者Stopped状态,系统可以将该Activity从内存中删除,Android系统采用两种方式进行删除,要么要求该Activity结束,要么直接终止它的进程。当该Activity再次显示给用户时,它必须重新开始和重置前面的状态。
3、Activity生命周期的分析
1、单个Activity的生命周期分析
Activity启动:
onCreate()–>onStart()–>onResume()点击home键回到主界面(Activity不可见):
onPause()–>onStop()再次回到Activity
onRestart()–>onStart()–>onResume()退出当前Activity
onPause()–>onStop()–>onDestroy()2、两个Activity切换时的生命周期分析
在ActivityA中启动ActivityB(ActivityA的onPause())—–>(ActivityB的生命周期方法onCreate()–>onStart()–>onResume())—–>(ActivityA的onStop())
1、为什么要先暂停当前显示的ActivityA?
2、为什么要先执行ActivityB的生命周期方法?
3、为什么不先执行ActivityA的onPause()–>onStop()的方法呢?解释:
1、比如当前Activity正在播放视频,突然一个电话打进来,此时要启动打电话的Activity,如果不先执行前一个Activity的OnPause()方法而直接执行打电话的Activity的生命周期方法的话,会造成前一个Activity的视频还在播放,但是界面是打电话的界面,用户体验不好2、如果先执行上一个Activity的OnStop()方法再执行下一个Activity的生命周期方法的话,如果第二个Activity闪退了,那么第一个Activity执行完OnStop()方法只后已经不可见了,此时屏幕是黑屏了。
4、Android的进程优先级
Android对于所有进程的处理态度都是尽可能不杀死。然而,资源总共就那么多,要是对所有进程都保持宽容的话,资源总会有消耗殆尽的时候。因此,在内存不足的情况,android系统需要根据一定的策略,选择性的杀死部分进程。这个策略就是对所有的进程标记优先级,优先级低的先杀死。
Android中将进程优先级分为5个层次,按照优先级由高到低排列:
1、前台进程(Foreground process)
a. 进程中包含处于前台的正与用户交互的activity;
b. 进程中包含与前台activity绑定的service;
c. 进程中包含调用了startForeground()方法的service;
d. 进程中包含正在执行onCreate(), onStart(), 或onDestroy()方法的service;
e. 进程中包含正在执行onReceive()方法的BroadcastReceiver.系统中前台进程的数量很少, 前台进程几乎不会被杀死. 只有当内存低到无法保证所有的前台进程同时运行时才会选择杀死某个前台进程.
2、可见进程
a. 进程中包含未处于前台但仍然可见的activity(调用了activity的onPause()方法, 但没有调用onStop()方法). 典型的情况是运行activity时弹出对话框, 此时的activity虽然不是前台activity, 但其仍然可见.
b. 进程中包含与可见activity绑定的service.3、服务进程
除了符合前台进程和可见进程条件的Service,其它的Service都会被归类为服务进程。
4、后台进程
持有不可见Activity(调用了onStop()方法)的进程即为后台进程。通常情况下都会有很多后台进程,当内存不足的时候,在所有的后台进程里面,会按照LRU(最近使用)规则,优先回收最长时间没有使用过的进程。
5、空进程
不包含任何处于活动状态的进程是一个空进程. 系统经常杀死空进程, 这不会造成任何影响. 空进程存在的唯一理由是为了缓存一些启动数据, 以便下次可以更快的启动.
二、Activity的启动模式
每个应用在启动时,安卓系统都会给该应用创建一个任务栈,不同的应用由不同的TaskID进行标识,栈用来管理打开的Activity
使用manifest文件
当在manifest文件中定义Activity的时候,你可以通过元素的launchMode属性来指定这个Activity应该如何与任务进行关联。launchMode属性一共有以下四种可选参数:
1、standard(默认启动模式)
standard是默认的启动模式,即如果不指定launchMode属性,则自动就会使用这种启动模式。这种启动模式表示每次启动该Activity时系统都会为创建一个新的实例,并且总会把它放入到当前的任务当中。声明成这种启动模式的Activity可以被实例化多次,一个任务当中也可以包含多个这种Activity的实例。2、singleTop(栈顶复用)
这种启动模式表示,如果要启动的这个Activity在当前任务中已经存在了,并且还处于栈顶的位置,那么系统就不会再去创建一个该Activity的实例,而是调用栈顶Activity的onNewIntent()方法。声明成这种启动模式的Activity也可以被实例化多次,一个任务当中也可以包含多个这种Activity的实例。举个例子来讲,一个任务的返回栈中有A、B、C、D四个Activity,其中A在最底端,D在最顶端。这个时候如果我们要求再启动一次D,并且D的启动模式是”standard”,那么系统就会再创建一个D的实例放入到返回栈中,此时栈内元素为:A-B-C-D-D。而如果D的启动模式是”singleTop”的话,由于D已经是在栈顶了,那么系统就不会再创建一个D的实例,而是直接调用D Activity的onNewIntent()方法,此时栈内元素仍然为:A-B-C-D。
3、singleTask(栈内复用)
这种启动模式表示,系统会创建一个新的任务,并将启动的Activity放入这个新任务的栈底位置。但是,如果现有任务当中已经存在一个该Activity的实例了,那么系统就不会再创建一次它的实例,并且将该Activity带到栈顶,把之前该Activity上面的其他的Activity全部销毁,会直接调用它的onNewIntent()方法。声明成这种启动模式的Activity,在同一个任务当中只会存在一个实例。注意这里我们所说的启动Activity,都指的是启动其它应用程序中的Activity,因为”singleTask”模式在默认情况下只有启动其它程序的Activity才会创建一个新的任务,启动自己程序中的Activity还是会使用相同的任务4、singleInstance
这种启动模式和”singleTask”有点相似,只不过系统不会向声明成”singleInstance”的Activity所在的任务当中再添加其它Activity。也就是说,这种Activity所在的任务中始终只会有一个Activity,通过这个Activity再打开的其它Activity也会被放入到别的任务当中。再举一个例子,Android系统内置的浏览器程序声明自己浏览网页的Activity始终应该在一个独立的任务当中打开,也就是通过在元素中设置”singleTask”启动模式来实现的。这意味着,当你的程序准备去打开Android内置浏览器的时候,新打开的Activity并不会放入到你当前的任务中,而是会启动一个新的任务。而如果浏览器程序在后台已经存在一个任务了,则会把这个任务切换到前台。
其实不管是Activity在一个新任务当中启动,还是在当前任务中启动,返回键永远都会把我们带回到之前的一个Activity中的。但是有一种情况是比较特殊的,就是如果Activity指定了启动模式是”singleTask”,并且启动的是另外一个应用程序中的Activity,这个时候当发现该Activity正好处于一个后台任务当中的话,就会直接将这整个后台任务一起切换到前台。此时按下返回键会优先将目前最前台的任务(刚刚从后台切换到最前台)进行回退
三、Scheme跳转协议
Uri结构的基本形式
[scheme:][//domain][path][?query][#fragment]
四、Activity状态恢复
在某些情况下,系统可能会对Activity进行重构(重新构建)
1、系统资源不够用时
2、切换系统语言
3、横竖屏切换在Activity重构的时候会导致数据丢失,Android系统提供了状态恢复机制用于保存Activity的状态
在onSaveInstanceState(Bundle outState)中保存数据
在onCreate(Bundle savedInstanceState)中恢复数据
或者在onRestoreInstanceState(Bundle savedInstanceState)中恢复数据横竖屏的切换
Activity在横竖屏切换时会销毁重建,目的就是为了读取新的布局文件
1、可以写死Activity的方向:
android:screenOrientation=”portrait”
android:screenOrientation=”landscape”2、配置Activity时添加以下属性,横竖屏切换时就不会销毁重建
android:configChanges=”orientation|screenSize|keyboardHidden”
配置完该属性后,就可以在横竖屏切换时不触发activity的生命周期方法,就可以防止在横竖屏切换时重构Activity
android:configChanges的作用就是 配置的属性值如果发生改变就不会导致Activity的重构,取而代之的是会调用onConfigurationChanged()方法