【原创】菜鸟版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的对应事件处理方法。

这张图完美的诠释了事件发生顺序。

image

从图上可以看到,有三个生存期:完整生存期、可见生存期、活动状态生存期。

完整生存期是从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集合。

image

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模式。最后的任务栈如下所示。

lip_image003

B. 两个Activity:MainActivity和SubActivitySingleTop,先启动MainActivity,MainActivity 启动single top 模式的SubActivitySingleTop, SubActivitySingleTop启动single top 模式SubActivitySingleTop。最后的任务栈如下所示。

lip_image004

C. 两个Activity:MainActivity和SubActivitySingleTask,先启动MainActivity,MainActivity 启动single task模式的SubActivitySingleTask, SubActivitySingleTask启动single task 模式SubActivitySingleTask。注意,启动两次SubActivitySingleTask。最后的任务栈如下所示。

lip_image005

从这个图看出,这与SingleTop表现一样啊,为什么?看下面。

D.两个Activity:MainActivity和SubActivityRealSingleTask,先启动MainActivity,MainActivity 启动single task模式的SubActivityRealSingleTask, SubActivityRealSingleTask启动single task 模式SubActivitySingleTask。注意,启动两次SubActivityRealSingleTask。与C不同的是,此次我设置了独立的taskAffinity这时候最后的任务栈如下所示。

lip_image006

罗升阳博客上说:“

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。这时:

lip_image007

然后SubActivityInter启动了SubActivityRealSingleTask。这时候最后的任务栈如下所示。

 

lip_image008

F. 三个Activity:MainActivity(single top)、SubActivitySingleInstance(single Intantce,未设置了affinity)和SubActivityInter2(standard)。MainActivity先启动SubActivitySingleInstance。图下

lip_image009

SubActivitySingleInstance启动SubActivityInter2,如下

lip_image010

SubActivityInter2启动MainActivity

lip_image011

注意:如果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 

posted @ 2016-10-11 09:46  stonehat  阅读(371)  评论(0编辑  收藏  举报