activity深入理解

来源:互联网 发布:台湾人深圳知乎 编辑:程序博客网 时间:2024/06/05 11:00

首先从activity的生命周期说起:

   一  首先看看android developers 网上的activity的生命周期图:

      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只保持着这个任务中当前会话那部分。如果用户离开,然后再返回这个任务,那么它就不再存在了。