【原创】菜鸟版Android 笔记2- Activity
1. Activity介绍
Acitivity在安卓开发中非常重要,他很像Java桌面开发中的JFrame,在MVC模式中属于Controller,一般一个应用程序通常由多个松耦合关系的activities组成,一个Activity是一个应用程序组件,控制一个View,用户可以用来交互。通常,当第一次启动应用程序的时候呈现给用户的那个activity被指定为 main activity。每一个activity然后可以启动另一个activity为了完成不同的动作。每一次一个activity启动,前一个activity就停止了,但是系统保留activity在一个栈上。当一个新activity启动,它被推送到栈顶,取得用户焦点。所以,当用户完成当前activity然后点击back按钮,它被弹出栈(并且被摧毁),然后之前的activity恢复。Activity的生命周期由Acitivity Manager管理。
A. Activity的种类有半透明的、悬浮的、全屏的。半透明、悬浮可以通过设置theme实现。它经常使用的类有Activity、ListActivity、ExpandableListActivity。
B. Android中,当应用程序运行环境改变时,设备的配置环境也许会发生变化(比如屏幕的旋转,键盘可用性的改变,语言的改变)。但是这些变化发生时,Android系统会重启Activity(onDestroy()将被调用,随后再调用onCreate()来创建Activity)。之所以这样设计,是想通过重新加载Activity来加载和新的配置环境相对应的资源,以便Activity能很好的适配新的配置环境。配置改变会导致Activity重启,可以定义android:configChanges来阻止重启。
C. 为了很好的处理Activity的重启,应该在Activity销毁前的系统回调函数中onSaveInstanceState() 保存其状态,然后在其重新被构建时的系统回调函数 onCreate() oronRestoreInstanceState()中,根据前面保存的状态来进行相应的设置。
2. Activity生命周期
要想能够自如的玩转Activity,深入的了解Activity的生命周期是必须的。
Activity从创建到消亡有活动、暂停、终止、非活动状态几种状态。
为了方便监控这些状态的变化,activity提供了事件处理方法,状态的变化会触发Activity的对应事件处理方法。
这张图完美的诠释了事件发生顺序。
从图上可以看到,有三个生存期:完整生存期、可见生存期、活动状态生存期。
完整生存期是从onCreate调用到onDestroy调用完成的状态,有时候不会调用destroy(例如断电)。
可见生存期是Activity可以被用户看到的时期(但是不一定有焦点):从onStart到onStop。
活动生存期是Activity可以与用户交互的时期:从onResume到onPause。
A. 当activity创建时,首先onCreate方法被调用,此时,可以调用setContentView设置Activity显示的View或者ViewGroup,也就是初始化UI和Activity的过程。
B. 如果这个Activity之前被运行时pause过(也就说显示过),那么onRestoreInstanceState会被调用,用来恢复界面状态(从Bundle)
C. 之后,可见生存期开始,onStart会被调用,可以开始启动UI更新了,可以启动线程、broadcastReceiver、传感器等。
D. 之后,活动状态开始,调用onResume,界面可以交互了。
E. 当activity要被要被stop之前(有时,非主动,被运行时因为内存问题stop),会调用onSaveInstanceState,如果该Activity被运行时终止并重启,那么被保存到bundle中的数据会被传递到oncreate和onRestoreInstanceState. 所以最好在oncreate里面判断一下是不是重新恢复创建的。
F. 当该启动了其他的Activity时,onPuase会被调用,此时可以挂起不需要更新的UI更新、线程和CPU密集的进程。
G. 当activity完全被遮盖时,onStop会被调用,此时应该挂起UI更新、线程和处理、传感器、broadcastReceiver。
H. 生命周期结束则会调用onDestroy,回收各项资源。
I. 图中onSave有误,大部分情况下都是在onPause后,onStop前。
当然,在Activity级别,也有像上文Application那样的事件处理函数。
事件处理函数 |
|
onLowMemory |
低内存事件触发,无参数 |
onTrimMemory(int) |
OnLowMemory是在最后一个后台进程被杀时调用,一般情况是low memory killer 杀进程后触发;而OnTrimMemory的触发更频繁,每次计算进程优先级时,只要满足条件,都会触发。 |
onConfigurationChanged(Configuration ) |
配置改变处理 |
3. Activity task和启动模式
在Android系统中,Activity组件的动态运行是通过task的,这种组织方法是面向组件开发的一种体现,比进程化得组织便利很多,task是将组件之间的连接,从进程概念的细节中剥离出来。同一个应用程序的不同Activity不一定在同一个task中,不同应用程序的activity也可以在同一个task中。Task其实是一个栈形式组织的Activity集合。
launchMode
<activity>元素的launchMode属性可以设置四种不同的加载模式:
A. standard (默认模式):会在当前调用者的task栈顶压入启动的activity。
B. singleTop:基本上于standard一致,仅在请求的Activity 正好位于栈顶时,有所区别。此时,配置成singleTop的Activity,不再会构造新的实例加入到Task栈中,而是将新来的Intent发送到栈顶Activity中,栈顶的Activity可以通过重载 onNewIntent来处理新的Intent。
C. singleTask:另辟Task。 标志为singleTask的Activity,最多仅有一个实例存在,并且,位于以它为根的Task中。所有对该Activity的请求,都会跳到该Activity的Task中展开进行。但是,需要设置singleTask的独立taskAffinity。
D. singleInstance:另辟Task。在大部分时候singleInstance与singleTask完全一致,唯一的不同在于,singleInstance的Activity,是它所在栈中仅有的一个Activity,如果涉及到的其他Activity,都移交到其他Task中进行。
taskAffinity
<activity>元素的taskAffinity属性,表示亲属关系,它倾向于将taskAffinity属性相同的Activity,扔进同一个Task中(即使是不同应用程序的activity)。不过,它的约束力,较之launchMode而言,弱了许多。只有当中的 allowTaskReparenting设置为true,或是调用方将Intent的flag添加 FLAG_ACTIVITY_NEW_TASK属性时才会生效。如果在manifest中没有对Activity的android:taskAffinity进行配置,每个Activity都采用和Application相同的taskAffinity;这也就意味着,同一个Application中的所有Activity的taskAffinity在默认情况下是相同的。
示例:
A.两个Activity:MainActivity和SubActivity,先启动MainActivity,MainActivity启动SubActivity, SubActivity启动SubActivity。Standard模式。最后的任务栈如下所示。
B. 两个Activity:MainActivity和SubActivitySingleTop,先启动MainActivity,MainActivity 启动single top 模式的SubActivitySingleTop, SubActivitySingleTop启动single top 模式SubActivitySingleTop。最后的任务栈如下所示。
C. 两个Activity:MainActivity和SubActivitySingleTask,先启动MainActivity,MainActivity 启动single task模式的SubActivitySingleTask, SubActivitySingleTask启动single task 模式SubActivitySingleTask。注意,启动两次SubActivitySingleTask。最后的任务栈如下所示。
从这个图看出,这与SingleTop表现一样啊,为什么?看下面。
D.两个Activity:MainActivity和SubActivityRealSingleTask,先启动MainActivity,MainActivity 启动single task模式的SubActivityRealSingleTask, SubActivityRealSingleTask启动single task 模式SubActivitySingleTask。注意,启动两次SubActivityRealSingleTask。与C不同的是,此次我设置了独立的taskAffinity这时候最后的任务栈如下所示。
罗升阳博客上说:“
1. 设置了“singleTask”启动模式的Activity,它在启动的时候,会先在系统中查找属性值affinity等于它的属性值taskAffinity的任务存在;如果存在这样的任务,它就会在这个任务中启动,否则就会在新任务中启动。因此,如果我们想要设置了“singleTask”启动模式的Activity在新的任务中启动,就要为它设置一个独立的taskAffinity属性值。
2. 如果设置了“singleTask”启动模式的Activity不是在新的任务中启动时,它会在已有的任务中查看是否已经存在相应的Activity实例,如果存在,就会把位于这个Activity实例上面的Activity全部结束掉,即最终这个Activity实例会位于任务的堆栈顶端中。
”
E. 三个Activity:MainActivity、SubActivityRealSingleTask(single task,设置了affinity)和SubActivityInter,先启动MainActivity,MainActivity 启动SubActivityRealSingleTask, SubActivityRealSingleTask启动standard模式SubActivityInter。这时:
然后SubActivityInter启动了SubActivityRealSingleTask。这时候最后的任务栈如下所示。
F. 三个Activity:MainActivity(single top)、SubActivitySingleInstance(single Intantce,未设置了affinity)和SubActivityInter2(standard)。MainActivity先启动SubActivitySingleInstance。图下
SubActivitySingleInstance启动SubActivityInter2,如下
SubActivityInter2启动MainActivity
注意:如果launchMode设置为standard,Affinity是无效的。
Intent flags:(启动Activity使用),这个很坑
FLAG |
解释 |
FLAG_ACTIVITY_NEW_TASK |
设置了这个flag,新启动Activity就会被放置到一个新的任务当中 |
FLAG_ACTIVITY_CLEAR_TOP |
要启动的Activity如果在当前Task中已经存在,就清除掉上面所有的Activity |
FLAG_ACTIVITY_SINGLE_TOP |
与Single Top类似 |
等等等等
任务清理
如果用户离开一个任务很长一段时间,系统会清理该任务中除了根activity之外的所有activity。不过可以用Activity以下属性控制这种行为:
alwaysRetainTaskState |
一直保留任务状态。如果一个任务的根activity中此属性设置为“true”,则上述默认行为不会发生。任务将在很长的一段时间内保留它堆栈内的所有activity。 |
clearTaskOnLaunch |
每次都会清空task,仅留下根Activity. 如果一个任务的根activity中此属性设置为“true”,则每当用户离开这个任务和返回它的时候,堆栈都会被清空至只留下根Activity。这正巧与alwaysRetainTaskState相反。 |
finishOnTaskLaunch |
仅作用于单个的activity,而不是整个的task。而且它可以使任意activity都被清理,甚至根activity也不例外。当它设置为“true”的时候,只要离开这个task栈, 则系统会马上清除这个Activity, 不管这个Activity在堆栈的任何位置。 |
任务栈要各个参数之间配合使用
4. Activity之切换
A. 直接调用,不需要知道结果,采用startActivity
B. 直接调用,需要知道结果,采用startActivityForResult(),并且重载onActivityResult方法。比较注意的是,当用户按back键的时候,系统会将resultCode置为RESULT_CANCELED,无法传递数据。
Intent result = new Intent(“com.example.RESULT_ACTION”, Uri.parse(“content://result_uri”);
setResult(Activity.RESULT_OK, result);
finish();
5. Activity系统调度
Activity的调度是依靠安卓框架中的Activity Manager Service。 framework框架中采用C/S的方式实现由后台服务ActivityManagerService来管理具体的Acitivity实例。
MainActivity的启动过程(根Activity)
A. Launcher组件想ActivityManagerService发送一个启动MainActivity组件的进程间通信请求。(Binder)
B. ActivityManagerService首先将要启动的MainActivity组件信息保存下来,然后像Launcher组件发送一个进入中止状态的进程间通信请求(Binder).
C. Launcher组件进入中止状态后,就会向ActivityManagerService报告自己中止状态已经进入。然后ActivityManagerService继续执行启动MainActivity。
D. ActivityManagerService发现运行MainActivity组件的进程不存在,他会启动一个进程。
E. 新进程启动完成后,就会给ActivityManagerService发送一个启动完成的通信,ActivityManagerService继续执行启动动作。
F. ActivityManagerService将第二步保存的MainActivity组件的信息发送给那个新进程,让他启动MainActivity组件。每个组件都是一个TaskRecord.
子组件启动过程
A. MainActivity组件向ActivityManagerService发送一个启动SubActivity的进程间通信请求。
B. ActivityManagerService将SubActivity的信息保存下来,然后向MainActivity发送一个进入终止状态的进程间通信请求。
C. MainActivity进入中止状态后,通过Binder报告已进入中止状态给ActivityManagerService。ActivityManagerService继续执行启动。
D. A发现运行Sub的进程已经存在,那么就将SubActivity的信息发送给那个进程,那个进程启动该组件。
Android应用程序进程创建严重依赖于Zygote进程(zygote是受精卵的意思,内涵),Zygote进程在内部拥有一个虚拟机实例,所以Zygote可以通过复制自身来快速创建虚拟机示例。创建出的 每个应用进程都拥有一个虚拟机(用来执行组件)、一个Binder线程池和一个消息循环(进程间通信)。
原创, 转载注明出处哦:http://www.cnblogs.com/stonehat/p/5947678.html