首先从activity的生命周期说起:
一 首先看看android developers 网上的activity的生命周期图:
![](https://lh5.googleusercontent.com/UYxzdGSnzQKE1EKXU00d5u06kUmA_sPHHBrjt7ria6OPP0nymujTqR0KWy_TE_lMDyPi-tj3byxAxAwJRiPNbbU4fGSNr6ZvUdSBJYJudYJRiZ2qxT8)
activity启动的时候:onCreate ---> onStart ---> onResume 这个过程不用多说,大家都知道。
这里主要讲讲: 何时onPause, 何时onStop,何时onDestory; 以及恢复的时候,何时onRestart,何时onResume。
为了方便说明这里把当前activity称为MainActivity,其他的activity称为SecondActivity、ThirdActivity等等。
通过上图的我们可以看出activity从running状态跳转到onPause状态的原因是:Another activity comes into the foreground. 也就是说有另外一个actvity被启动并运行了,比如说MainActivity通过startActivity启动了SecondActivity,那么SecondActivity就在ui视图的最顶层了,而MainActivity不再是最顶层的activity了,此时就会onPause了,此时我们依稀还能看到MainActivity,只是MainActivity已经站在他人之后了。
而当MainActivity完全被SecondActivity挡住,完全看不见的时候,此时MainActivity就会onStop了。我们看看上图从onPause到onStop的原因是:the activity is no longer visiable. 也就是说此时MainActivity完全不可见了,从这里我们可以猜测当按下home键的时候,当前activity就会处于onStop的状态。
从actvitiy的生命周期图中,我们可以看出activity是可以停留在onPause和onStop在这两个状态上的,因为可以相应的恢复。
那么何时停留在onPause,何时停留在onStop呢?
下图的MainActivity就是处于onPause状态:
因为这里的second actvity是dialog样式:
<activity android:name=".SecondActivity" android:theme="@android:style/Theme.Dialog">
也就验证了当MainActivity不再在最顶端,但仍然可见的时候,MainActivity就处于onPause状态,此时如果退出(back键)second activity,那么MainActivity就会onResume。
下图的MainActivity就是处于onStop状态(注意,这里的third activity 是在 MainActivity中通过startActivity启动的):
因为此时MainActivity已经完完全全被Thrid actvity挡住了,完全不可见了,所以MainActivity处于onStop状态,如果此时退出Thrid activity(back键),那么MainActivity就会onRestart().
何时onDestory呢?
当在MainActivity中按back键,退出时,最终就会走到onDestory,或者在代码中调用finish()的时候也会走到onDestroy这一步。
对于activity生命周期图的左侧部分:
当MainActivity处于onPause和onStop状态时,当更高优先级的apps需要内存,而此时系统内存不够了,那么android系统就会将MainActivity所在的进程给杀了以释放资源。
当然被杀了之后,想重生,那必须得从头来过: onCreate ---> onStart() ---> onResume().
看到这里activity的生命周期基本上了解,但在实际开发过程中,还有其他的情况必须考虑。
二.横竖屏切换:
1、按crtl+f12切换成横屏时
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->
2、再按crtl+f12切换成竖屏时,发现打印了两次相同的log
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->
3、修改AndroidManifest.xml,把该Activity添加 android:configChanges="orientation",执行步骤1
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->
4、再执行步骤2,发现不会再打印相同信息,但多打印了一行onConfigChanged
onSaveInstanceState-->
onPause-->
onStop-->
onDestroy-->
onCreate-->
onStart-->
onRestoreInstanceState-->
onResume-->
onConfigurationChanged-->
5、把步骤5的android:configChanges="orientation" 改成 android:configChanges="orientation|keyboardHidden",
执行步骤1,就只打印onConfigChanged
onConfigurationChanged-->
6、执行步骤2
onConfigurationChanged-->
onConfigurationChanged-->
总结:
1、不设置Activity的android:configChanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2、设置Activity的android:configChanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3、设置Activity的android:configChanges="orientation|keyboardHidden"时,切屏不会重新调用各个生命周期,只会执行onConfigurationChanged方法
三.那到了这里,其实还没完,锁屏的时候activity的生命周期同样也会发生变化:
锁屏时 系统销毁当前Activity又在后台创建了一个Activity ,再解锁时 系统又销毁了后台的Activity 再创建一个新的Activity。
起初不是很明白,后来在网上查了相关资料发现这中情况是由于横竖屏切换引起的,横竖屏切换时 会销毁当前Activity 再创建 一个新的Activity(横屏切竖屏或者竖屏切横屏)。具体过程大家可以写个demo 打上日志看看 ,这里就不细说了,至于为什么要这样设计还有待研究,下面就来看看这个问题的解决方法:
解决这个问题 只要在程序的配置文件 (APPManifest.xml ,的相关Activity里加上
android:configChanges=”keyboard|keyboardHidden|orientation”
加上这句后 按锁屏键 就不会销毁当前Activity 也不会在后台创建Activity了 ,其生命周期类似于按了Home键的过程。
总结一下整个Activity的生命周期
补充一点,当前Activity产生事件弹出Toast和AlertDialog的时候Activity的生命周期不会有改变
Activity运行时按下HOME键(跟被完全覆盖是一样的):onSaveInstanceState --> onPause --> onStop onRestart -->onStart--->onResume
Activity未被完全覆盖只是失去焦点:onPause--->onResume
四 activity的属性
activity是android中使用非常平凡的一种组件,我们除了需要掌握activity中的生命周期以外,还需要掌握activity中的其
他设置。
1.activity 中主题的设置
android中我们可以通过AndroidManifest.xml中设置activity中的主题,其实android提供了许多自带的主题样式,如下:
android:theme="@android:style/Theme.Dialog" 将一个Activity显示为能话框模式
android:theme="@android:style/Theme.NoTitleBar" 不显示应用程序标题栏
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 不显示应用程序标题栏,并全屏
android:theme="Theme.Light" 背景为白色
android:theme="Theme.Light.NoTitleBar" 白色背景并无标题栏
android:theme="Theme.Light.NoTitleBar.Fullscreen" 白色背景,无标题栏,全屏
android:theme="Theme.Black" 背景黑色
android:theme="Theme.Black.NoTitleBar" 黑色背景并无标题栏
android:theme="Theme.Black.NoTitleBar.Fullscreen" 黑色背景,无标题栏,全屏
android:theme="Theme.Wallpaper" 用系统桌面为应用程序背景
android:theme="Theme.Wallpaper.NoTitleBar" 用系统桌面为应用程序背景,且无标题栏
android:theme="Theme.Wallpaper.NoTitleBar.Fullscreen" 用系统桌面为应用程序背景,无标题栏,全屏
android:theme="Translucent"
android:theme="Theme.Translucent.NoTitleBar" 透明,无标题栏
android:theme="Theme.Translucent.NoTitleBar.Fullscreen" 透明,无标题栏,并且全屏显示
android:theme="Theme.Panel"
android:theme="Theme.Light.Panel"
我们可以通过需求来设置不同的主题。
2.android 中activity横竖屏设置
由于手机可以支持横竖屏切换,当android进行切换时可以回对页面中的布局照成影响,当在AndroidManifest.xml文件中定义了android:screenOrientation="portrait",就表示当我们切换横竖屏的时候,屏幕的内容始终以竖屏显示,而不会根据屏幕的方向来显示内容。而设置为android:screenOrientation="landscape"则为横屏显示。
3.android中activity中launchMode属性的几种值说明
launchMode 中的是四种状态
standard:每次都创建一个实例,默认将Activity加入到当前Task。
singleTop:启动的不是当前的Activity的话,则创建一个实例,并加入当前Task,否则抛弃 ,Intent不做任何反应
singleTask:只有一个Task,不会重新创建已存在的Activity。
singleInstance:一个Task里只有一个Activity。启动Acivity时,会重新创建一个Task,并把Activity加入新建的Task。
例如:如果用户长时间的离开一个任务,那么系统会清除这个任务根Activity以外的所有Activity。当用户再次返回这个任务时,只有根Activity被存储。系统行为的这种方式是因为经过长时间以后,用户在返回这个任务之前可能已经放弃它们的作业,而开始了某些新的任务。
你能够使用一些Activity属性来修改这种行为
1.alwaysRetainTaskState
如果这个属性在一个任务的根Activity中被设置为“true”,那么像上面描述的那样的默认行为就不会发生。即使是长时间之后,这个任务也会在它的堆栈中保留所有的Activity。
2.clearTaskOnLaunch
如果这个属性在一个任务的根Activity中被设置为“true”,那么无论用户什么时候离开和返回这个任务,堆栈都会被清除到根Activity的位置。换句话说,它与alwaysRetainTaskState属性相反,用户总是返回到任务的初始状态,即使只离开这个任务一会儿。
3.finishOnTaskLaunch
这个属性点像clearTaskOnLaunch属性,但是它只操作单个Activity,而不是整个任务。它也能导致任何Activity离开,包括根Activity。当这个属性设置为“true”时,这个Activity只保持着这个任务中当前会话那部分。如果用户离开,然后再返回这个任务,那么它就不再存在了。