(4.1.1)基础总结篇之一:Activity生命周期

一、Activity

  • activity类处于android.app包中,继承体系如下:
  1. java.lang.Object
  2. android.content.Context
  3. android.conten.ContextWrapper
  4. android.view.ContextThemeWrapper
  5. android.app.Activity
  • Activity在Android系统中用一个LIFO机制的Activity栈来管理
  • 当新的Activity[A]启动时,它就被放在了Activity栈的顶端,而进入运行状态,而先前运行的Activity[B]通常就被放在了Activity栈里A的下面
  • 当A退出运行而从Activity栈顶出栈之后,B就成了Activty栈的最上面的Activity,可再次进入前台运行状态。

activity是单独的,用于处理用户操作。几乎所有的activity都要和用户打交道,所以activity类创建了一个窗口,开发人员可以通过setContentView(View)接口把UI放到activity创建的窗口上,当 activity指向全屏窗口时,也可以用其他方式实现:作为漂浮窗口(通过windowIsFloating的主题集合),或者嵌入到其他的 activity(使用ActivityGroup)

  • Activity子类都需要实现以下两个接口:
  • onCreate(Bundle)接口是初始化activity的地方. 在这儿通常可以调用setContentView(int)设置在资源文件中定义的UI, 使用findViewById(int) 可以获得UI中定义的窗口.
  • onPause()接口是使用者准备离开activity的地方,在这儿,任何的修改都应该被提交(通常用于ContentProvider保存数据).

为了能够使用Context.startActivity(),所有的activity类都必须在AndroidManifest.xml文件中定义有相关的“activity”项。

二、生命周期

这里写图片描述

Activity有四种本质区别的状态:

  1. 在屏幕的前台(Activity栈顶),叫做活动状态或者运行状态(active or running)
  2. 如果一个Activity失去焦点,但是依然可见(一个新的非全屏的Activity 或者一个透明的Activity 被放置在栈顶),叫做暂停状态(Paused)。一个暂停状态的Activity依然保持活力(保持所有的状态,成员信息,和窗口管理器保持连接),但是在系统内存极端低下的时候将被杀掉。
  3. 如果一个Activity被另外的Activity完全覆盖掉,叫做停止状态(Stopped)。它依然保持所有状态和成员信息,但是它不再可见,所以它的窗口被隐藏,当系统内存需要被用在其他地方的时候,Stopped的Activity将被杀掉。
  4. 如果一个Activity是Paused或者Stopped状态,系统可以将该Activity从内存中删除,Android系统采用两种方式进行删除,要么要求该Activity结束,要么直接杀掉它的进程。当该Activity再次显示给用户时,它必须重新开始和重置前面的状态。

对应的,Activity有三个关键的循环:

  1. 整个的生命周期,从onCreate(Bundle)开始到onDestroy()结束。
  • Activity在onCreate()设置所有的“全局”状态,在onDestory()释放所有的资源。例如:某个Activity有一个在后台运行的线程,用于从网络下载数据,则该Activity可以在onCreate()中创建线程,在onDestory()中停止线程。
  1. 可见的生命周期,从onStart()开始到onStop()结束。
  • 在这段时间,可以看到Activity在屏幕上,尽管有可能不在前台,不能和用户交互。在这两个接口之间,需要保持显示给用户的UI数据和资源等,例如:可以在onStart中注册一个IntentReceiver来监听数据变化导致UI的变动,当不再需要显示时候,可以在onStop()中注销它。onStart(),onStop()都可以被多次调用,因为Activity随时可以在可见和隐藏之间转换。
  1. 前台的生命周期,从onResume()开始到onPause()结束。
  • 在这段时间里,该Activity处于所有 Activity的最前面,和用户进行交互。Activity可以经常性地在resumed和paused状态之间切换,例如:当设备准备休眠时,当一个 Activity处理结果被分发时,当一个新的Intent被分发时。所以在这些接口方法中的代码应该属于非常轻量级的。

2.1 onNewIntent

一般在onRestart之前调用

在默认情况下,当您通过Intent启到一个Activity的时候,就算已经存在一个相同的正在运行的Activity,系统都会创建一个新的Activity实例并显示出来。为了不让Activity实例化多次,我们需要通过在AndroidManifest.xml配置activity的加载方式(launchMode)以实现单任务模式

launchMode为singleTask的时候,通过Intent启到一个Activity,如果系统已经存在一个实例,系统就会将请求发送到这个实例上,但这个时候,系统就不会再调用通常情况下我们处理请求数据的onCreate方法,而是调用onNewIntent方法

系统可能会随时杀掉后台运行的 Activity ,如果这一切发生,那么系统就会调用 onCreate 方法,而不调用 onNewIntent 方法,一个好的解决方法就是在 onCreate 和 onNewIntent 方法中调用同一个处理数据的方法

第一种情况:activity launchMode为singleTask或者singleInstance

1. activitya start activityb
2. activityb start activitya

在第二步被执行后,activitya就会顺序执行 onNewIntent-onRestart-onStart-onResume

第二种情况:activity launchMode为singleTop singleTask singleInstance

1. start activitya
2. activitya start activitya

在第二步被执行后,activitya就会顺序执行onPause-onNewIntent-onResume

第一种情况其实是真正的activity被restart,第二种情况是activity位于栈顶时被再次start就会进入onNewIntent

2.2 onActivityResult

在onRestart之前调用

如果被启动的Activity的launch mode为SingleInstacne或SignleTask,且不论是从Activity还是从Fragment启动该Activity都会造成这种情况"调用startActivityForResult后onActivityResult被立即触发",所以根据实际情况修改launch mode即可

总结下onActivityResult执行错误常见原因:

  • 待跳转的Activity启动模式错误:

  • standard与singletop模式是会在跳转后的Activity finish后执行onActivityResult,而singletask和singleinstance模式是在startActivityforresult后立即执行onActivityResult;

  • startActivityforresult()的第二个参数requestCode必须>=0,而且<0xffff

  • 在TabHost的子Activity中startActivityForResult调用其他Activity时候遭遇到onActivityResult方法不响应:
    这个问题主要还是和activitygroup有关,不过TabHost也是过时很久了,最好不要用

  • 调用startactivityforresult的activity与跳转的activity finish后返回的activity必须是同一个

2.3 onWindowFocusChanged

被开启的Activity在onResume之后立即调用
被关闭的Activity在另一个Activity的onResume后调用

当前窗体得到或失去焦点的时候的时候调用。这是这个活动是否是用户可见的最好的指标。默认的实现清除重点跟踪状态,所以应该总是被调用。

在Activity的生命周期中,onCreate()–onStart()–onResume()都不是窗体Visible的时间点,真正的窗体完成初始化可见获取焦点可交互是在onWindowFocusChanged()方法被执行时,而这之前,对用户的操作需要做一点限制。

比如我们在做OTT项目时候,我们就是在这onWindowFocusChanged来获取主按键的具体位置和宽高的,而在其他标准生命周期的接口中调用都是获取不到的,比如在onResume,onStart中都获取不到信息。
这个onWindowFocusChanged指的是这个Activity得到或者失去焦点的时候 就会call

请注意,这提供了有关整体焦点状态信息,这是独立管理活动的生命周期。因此,焦点的变化通常会有一些关系生命周期变化(一种活动停止一般不会得到窗口焦点),你应该不依赖于任何特定的顺序之间的回调在这里和那些在其他生命周期方法如onresume()。作为一般规则,然而,一个恢复活动将得到窗口焦点…除非有其他对话框弹出窗口显示或接受输入焦点,在这种情况下,活动本身不会有焦点时,其他窗口拥有它。同样,系统会显示系统顶层窗口(如状态栏通知面板或警报系统)将暂时不停顿的前台活动带窗口的输入焦点。

2.4 onSaveInstanceState 和 onRestoreInstanceState

  • onSaveInstanceState 的调用顺序是在onPause之前
  • onRestoreInstanceState的调用顺序是在onStart之后
  • 两者并不匹配出现,onRestoreInstanceState只有在杀死不在前台的Activity之后用户回到此Activity,或者用户改变屏幕方向的这两个重建过程中被调用
  • onSaveInstanceState
  • 在Activity被覆盖或退居后台之后,系统资源不足将其杀死,此方法会被调用;
  • 在用户改变屏幕方向时,此方法会被调用;
  • 在当前Activity跳转到其他Activity或者按Home键回到主屏,自身退居后台时,此方法会被调用。

第一种情况我们无法保证什么时候发生,系统根据资源紧张程度去调度;第二种是屏幕翻转方向时,系统先销毁当前的Activity,然后再重建一个新的,调用此方法时,我们可以保存一些临时数据;第三种情况系统调用此方法是为了保存当前窗口各个View组件的状态。onSaveInstanceState的调用顺序是在onPause之前。

  • onRestoreInstanceState
  • 在Activity被覆盖或退居后台之后,系统资源不足将其杀死,然后用户又回到了此Activity,此方法会被调用;

2.5 onConfigurationChanged

1.指定为竖屏:在AndroidManifest.xml中对指定的Activity设置android:screenOrientation=“portrait”,或者在onCreate方法中指定:

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);  //竖屏  

三、示例

onCreate
->onAttachFragment
->onContentChanged
(->onActivityResult)
(->onNewIntent)
->onStart
->onRestoreInstanceState
->onPostCreate
->onResume
->onPostResume
->onAttachToWindow
->onCreateOptionsMenu
->onPrepareOptionMenu
->(Activity在运行时可能回调的方法:onUserInteraction/onUserLeawerHint)
->onSaveInstanceState
->onPause
->onStop
->onDestroy

相信不少朋友也基本了解了Activity生命周期的几个过程,我们就来说一说这几个过程。

  1. 启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。
  2. 当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。
  3. 当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。标示焦点性,不失去焦点,则不触发
  4. 当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台或者锁屏:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。标示可见性,如果还可见,则不触发onStop(譬如,上边弹出个对话框)
  5. 用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。
  6. 当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。
  7. 用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。
  • Intent跳转时一定会走到当前Activity的onPause才跳转,至于onStop调不调,要看新的界面是否完全遮盖旧的

冷启动过程

11-06 14:12:01.791 16683-16683/? I/MainActivity: onCreate()
11-06 14:12:01.791 16683-16683/? I/MainActivity: onStart()
11-06 14:12:01.791 16683-16683/? I/MainActivity: onPostCreate()
11-06 14:12:01.791 16683-16683/? I/MainActivity: onResume()
11-06 14:12:01.791 16683-16683/? I/MainActivity: onPostResume()
11-06 14:12:01.821 16683-16683/? I/MainActivity: onAttachedToWindow()
11-06 14:12:01.861 16683-16683/? I/MainActivity: onWindowFocusChanged():true  

按Home件进入系统界面

11-06 14:12:26.231 16683-16683/sangfor.com.teststaticlife I/MainActivity: onPause()
11-06 14:12:26.241 16683-16683/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged():false  
11-06 14:12:26.771 16683-16683/sangfor.com.teststaticlife I/MainActivity: onStop()

热启动过程

11-06 14:12:38.731 16683-16683/sangfor.com.teststaticlife I/MainActivity: onRestart()
11-06 14:12:38.741 16683-16683/sangfor.com.teststaticlife I/MainActivity: onStart()
11-06 14:12:38.741 16683-16683/sangfor.com.teststaticlife I/MainActivity: onResume()
11-06 14:12:38.741 16683-16683/sangfor.com.teststaticlife I/MainActivity: onPostResume()
11-06 14:12:38.751 16683-16683/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged():true  

长按home键触发最近任务栈

11-06 14:13:13.751 16683-16683/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged():false  

锁屏

11-28 17:24:57.027 14726-14726/sangfor.com.teststaticlife I/MainActivity: onPause()
11-28 17:24:57.117 14726-14726/sangfor.com.teststaticlife I/MainActivity: onStop()
11-28 17:24:58.017 14726-14726/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged():false  

解锁

11-28 17:25:53.667 14726-14726/sangfor.com.teststaticlife I/MainActivity: onRestart()
11-28 17:25:53.687 14726-14726/sangfor.com.teststaticlife I/MainActivity: onStart()
11-28 17:25:53.697 14726-14726/sangfor.com.teststaticlife I/MainActivity: onResume()
11-28 17:25:53.697 14726-14726/sangfor.com.teststaticlife I/MainActivity: onPostResume()
11-28 17:25:53.797 14726-14726/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged():true  
11-28 17:25:56.087 14726-14726/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged():true  

原始在前台—>长按home键触发最近任务栈—>从任务栈唤醒

11-06 14:13:36.701 16683-16683/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged():true  

原始在后台—>长按home键触发最近任务栈—>从任务栈唤醒

11-06 14:14:47.831 16683-16683/sangfor.com.teststaticlife I/MainActivity: onRestart()
11-06 14:14:47.841 16683-16683/sangfor.com.teststaticlife I/MainActivity: onStart()
11-06 14:14:47.841 16683-16683/sangfor.com.teststaticlife I/MainActivity: onResume()
11-06 14:14:47.841 16683-16683/sangfor.com.teststaticlife I/MainActivity: onPostResume()
11-06 14:14:48.201 16683-16683/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged()

MainActivity跳转到SecondActivity

11-06 14:59:09.821 16683-16683/sangfor.com.teststaticlife I/MainActivity: onPause()  
11-06 14:59:09.841 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onCreate()  
11-06 14:59:09.851 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onStart()  
11-06 14:59:09.851 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onPostCreate()  
11-06 14:59:09.851 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onResume()  
11-06 14:59:09.851 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onPostResume()  
11-06 14:59:09.861 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onAttachedToWindow()  
11-06 14:59:09.901 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onWindowFocusChanged():true  
11-06 14:59:09.941 16683-16683/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged():false  
11-06 14:59:10.311 16683-16683/sangfor.com.teststaticlife I/MainActivity: onStop() 

SecondActivity返回到MainActivity

11-06 15:00:17.531 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onPause()  
11-06 15:00:17.541 16683-16683/sangfor.com.teststaticlife I/MainActivity: onRestart()  
11-06 15:00:17.541 16683-16683/sangfor.com.teststaticlife I/MainActivity: onStart()  
11-06 15:00:17.541 16683-16683/sangfor.com.teststaticlife I/MainActivity: onResume()  
11-06 15:00:17.541 16683-16683/sangfor.com.teststaticlife I/MainActivity: onPostResume()  
11-06 15:00:17.581 16683-16683/sangfor.com.teststaticlife I/MainActivity: onWindowFocusChanged():true  
11-06 15:00:17.621 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onWindowFocusChanged():false  
11-06 15:00:17.911 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onStop()  
11-06 15:00:17.911 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onDestroy()  
11-06 15:00:17.911 16683-16683/sangfor.com.teststaticlife I/SecondActivity: onDetachedFromWindow()  

Activity的onCreate中启动新的Activity时生命周期

11-23 09:41:37.597 4115-4115/? I/MainActivity: onCreate()
11-23 09:41:37.607 4115-4115/? I/MainActivity: onStart()
11-23 09:41:37.607 4115-4115/? I/MainActivity: onPostCreate()
11-23 09:41:37.607 4115-4115/? I/MainActivity: onResume()
11-23 09:41:37.607 4115-4115/? I/MainActivity: onPostResume()
11-23 09:41:37.617 4115-4115/? I/MainActivity: onPause()
11-23 09:41:37.627 4115-4115/? I/MainActivity: onAttachedToWindow()
11-23 09:41:37.647 4115-4115/? I/SecondActivity: onCreate()
11-23 09:41:37.647 4115-4115/? I/SecondActivity: onStart()
11-23 09:41:37.647 4115-4115/? I/SecondActivity: onPostCreate()
11-23 09:41:37.647 4115-4115/? I/SecondActivity: onResume()
11-23 09:41:37.647 4115-4115/? I/SecondActivity: onPostResume()
11-23 09:41:37.657 4115-4115/? I/SecondActivity: onAttachedToWindow() 
11-23 09:41:37.707 4115-4115/? I/SecondActivity: onWindowFocusChanged():true  
11-23 09:41:38.307 4115-4115/? I/MainActivity: onStop()

旋转屏幕

11-23 09:41:37.607 4115-4115/? I/MainActivity: onSaveInstanceState()
11-23 09:41:37.617 4115-4115/? I/MainActivity: onPause()
11-23 09:41:38.307 4115-4115/? I/MainActivity: onStop()
11-23 09:41:38.307 4115-4115/? I/MainActivity: onDestory()
11-23 09:41:39.647 4115-4115/? I/MainActivity: onCreate()
11-23 09:41:39.647 4115-4115/? I/MainActivity: onStart()
11-23 09:41:39.647 4115-4115/? I/MainActivity: onRestoreInstanceState()
11-23 09:41:39.647 4115-4115/? I/MainActivity: onResume()
11-23 09:41:39.647 4115-4115/? I/MainActivity: onPostResume()
11-23 09:41:39.707 4115-4115/? I/MainActivity: onWindowFocusChanged():true  

旋转屏幕 + android:configChanges=“orientation”

11-23 09:41:39.707 4115-4115/? I/MainActivity: onConfigurationChanged():true  

1.如果配置了android:screenOrientation属性,则会使android:configChanges="orientation"失效。

2.模拟器与真机差别很大:模拟器中如果不配置android:configChanges属性或配置值为orientation,切到横屏执行一次销毁->重建,切到竖屏执行两次。真机均为一次。模拟器中如果配置android:configChanges=“orientation|keyboardHidden”(如果是Android4.0,则是"orientation|keyboardHidden|screenSize"),切竖屏执行一次onConfigurationChanged,切横屏执行两次。真机均为一次

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值