Activity的生命周期和启动模式
2016-01-13 14:58
309 查看
Activity的生命周期
典型情况下的生命周期分析
onCreate()第一个生命周期方法,一般在这个方法做初始化工作,比如调用setContentView去加载界面布局资源,初始化Activity所需要的数据等。
onStart()
onRestart()
onResume()
onPause()
可见,但不可交互的情况。一般在这个方法做一些动画暂停操作。同时,onPause()必须先执行完,新的Activity的onResume()才能执行。
onStop()
可做一些稍重量级的回收工作
oDestory()
Activity生命周期里的最后一个回调方法,一般在这里做垃圾回收和资源释放工作。
问题1:
当前Activity为A,用户打开一个新的ActivityB,那么B的onResume()和A的onPause()哪个先执行?
答:Activity的启动过程比较复杂,涉及Instrumentation、ActivityThread和ActivityManagerService(简称:AMS)。简单来说,启动Activity的请求会有Instrumentation来处理,然后它通过Binder小AMS发送请求,AMS内部维护着一个ActivityStack并负责着栈内Activity的状态同步,AMS通过ActivityThread去同步Activity的状态从而完成生命周期的调用。
具体解析:P4-P6
异常情况下的生命周期分析
资源相关的系统配置发送改变导致Activity被杀死被重新创建。资源内存不足导致低优先级的Activity被杀死。
如果一个进程中没有四大组件在执行,那么这个进程将很快被系统杀死,所以后台操作适合放入Service中从而保证进程的优先级。
[b]onSaveInstanceState()/onRestoreInstanceState()[/b]
Activity:
在Activity异常终止的时候,系统会调用onSaveInstanceState()来保存Activity的状态,这个方法的调用时机在onStop()之前,可能在onPause()之前,也可能在它之后。当Activity被重新创建的时候,系统或调用onRestoreInstanceState(),并把之前在onSaveInstanceState()所保存的Bundle对象作为参数同时传递给onRestoreInstanceState()和onCreate()方法。onRestoreInstanceState()会在onStart()之后调用。
View:
当Activity在异常情况下需要重新创建的时候,系统会默认为我们保存当前Activity的视图结构,并在重建的时候为我们恢复这些数据,比如文本框中输入的数据,ListView的滚动位置等,这些View相关的状态系统都默认为我们保存恢复,根据View的源码。和Activity一样,每个View都有onSaveInstanceState()/onRestoreInstanceState()。恢复流程:首先Acitivity被意外终止,Activity调用onSaveInstanceState()保存数据,然后Activity会委托Window保存数据,接着Window再委托它上面的顶级容器去保存数据。顶级容器是一个ViewGroup,一般来说它很可能是DecorView。最后顶级容器在一一去通知它的子元素来保存数据。这是一种典型的委托思想,上层委托下层,比如View的绘制,事件的分发等都用到了这种思想。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_diy_view); //可以直接在onCreate中判断并恢复 if(savedInstanceState != null){ String temp_str = savedInstanceState.getString("flag"); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putString("flag","需要保存的参数"); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); String temp_str = savedInstanceState.getString("flag"); }
系统配置
横竖屏切换,不重新创建Activity,只需要在AndroidMenifest.xml中的相应的Activity加入:android:configChanges=”orientation|screenSize”即可,代码如下:
<activity android:name=".activitys.DiyViewActivity" android:launchMode="singleTop" android:configChanges="orientation|screenSize" </activity>
Activity的启动模式
给Activity设置启动模式第一种:android:launchMode=”singleTask”
第二种:intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
不同点:
1.优先级上,两种方式同时存在的时候以第二种为准。
2.第一张无法直接为Activity设定FLAG_ACTIVITY_CLEAR_TOP标识的效果,而第二种方法无法为Activity指定singleInstance模式。
standard:标准模式
注意:
在这种模式下,谁启动这个Activity,那么这个Activity就运行这启动它的那个Activity所在的栈中。所以,当用ApplicationContext去启动standard模式的Activity的时候会报错。因为非Activity类型的Context(如Application)并没有所谓的任务栈。
解决方法:用Activity类型的Context去启动,或给待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位。
/* 这时候启动的Activity实际是以singleTask模式启动的。因为类似CSS的最近原则,当launchMode和setFlags同时存在的时候,以setFlags为准。 */ Intent intent = new Intent(); intent.setClass(DiyViewActivity.this,SpinnerActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent);
singleTop:栈顶复用模式
如果待启动的Activity已经存在于栈顶则此Activity不会重新创建实例,同时它的onNewIntent()会被回调。通过这个方法的参数我们可以取出当前请求的信息。
@Override protected void onResume() { super.onResume(); log("onResume"); if(flag){ Intent intent = new Intent(this,DiyViewActivity.class); startActivity(intent); flag=flase; } } /* 输出: onCreate 输出: onStart 输出: onResume 输出: onPause//Activity会先暂停(不可交互),然后调用onNewIntent() 输出: onNewIntent 输出: onResume */
Activity第一启动的时候执行onCreate()—>onStart()—>onResume()等后续生命周期函数,也就时说第一次启动Activity并不会执行到onNewIntent(). 而后面如果再有想启动Activity的时候,那就是执行onNewIntent()—->onResume(). 如果android系统由于内存不足把已存在Activity释放掉了,那么再次调用的时候会重新启动Activity即执行onCreate()—>onStart()—>onResume()等。
注意:
当调用到onNewIntent(intent)的时候,需要在onNewIntent() 中使用setIntent(intent)赋值给Activity的Intent.否则,后续的getIntent()都是得到老的Intent。
singleTask:栈内复用模式
这是一种单实例模式,如果栈中已经存在,则会调用onNewIntent。具体一点,例如要启动ActivityA,系统首先会寻找是否存在ActivityA想要的任务栈,如果不存在,则创建,然后创建ActivityA后把它发到该任务栈中。
singleInstance:单实例模式。
一种加强的singleTask模式,具有singleTask的所有特性,同时该模式的Activity只能单独位于一个任务栈中。
注意
现在有2个任务栈,前台任务栈为AB,后台任务栈情况为CD,这里假设CD的启动模式均为singTask。现在请求启动D,那么整个后台任务栈都会被切换到前台,这个时候整个后退列表为ABCD,按back键的时候会先弹出D。
相关文章推荐
- java(12)--小应用-基于xml的简单考试查询系统
- Ubuntu下安装词典
- LevelDB windows vs2013 c++编译和测试
- libvirt虚拟系统如何增加usb设备
- git命令详解
- OGG迁移到12C后,提示参数冲突(OGG-10107 )
- 对9取余
- 2199: [Usaco2011 Jan]奶牛议会 2-SAT
- JVM内存区域总结
- Swift基础--使用TableViewController自定义列表
- 通过因特网连接Beaglebone Black
- Android之史上最全最简单最有用的第三方开源库收集整理
- java ftp 上传文件
- Android Eclipse 修改默认查看图片的打开方式
- poj2488A Knight's Journey--简单搜索
- 定时器
- Linux 多个快速切换目录
- xcode调试教程
- 两个ArrayList<String>() 的并集,交集,差集
- 关于影像颜色替换