Android之Activity分析

来源:互联网 发布:网格最短路径算法 编辑:程序博客网 时间:2024/06/05 18:41

  Android之Activity分析

本文的主要内容是介绍androidactivity,内容由我总结各方总结分析加之自己的理解,所涉及肯定不完全,尽我所能知道的写吧。

此文档分为以下几个部分:

1、Activity的简单介绍

2、Activity的启动与关闭

3、使用Bundle在Activity之间传递数据

4、Activity的生命周期

5、Activity的状态及状态变换

6、进程生命周期

7、配置Activity

1Activity的简单介绍

什么是Activity

这个问题很难回答,直译为活动;Android提供的解释是:An activity is a single, focusedthing that the user can do;简单翻译一下就是,activity是用户可与之交互的独立的可以聚焦的东西;它可以为用户提供的是一个简单的Window,用户可用于堆放自己想要的UI效果;

Activity是一个线程或者进程吗?

Activity肯定会存在于某个进程,但是并不是每一个activity都对应于一个新的进程,多个activity可以在同一个进程里面,甚至多个应用还可以在同一个进程里面;当然可以设置不同的LaunchMode让一个activity起来的时候创建一个进程,但它本身肯定不是线程或者进程,但它通常是这个进程的主角;

Activity本身的执行逻辑是怎么样的?

这个就涉及activity最重要的生命周期的问题,后面会详细的解释,简单说从onCreate开始,到onDestory结束,但如果你通过打印信息来看的话,经常会发现onDestory似乎没被执行,更确切的说,你并不知道它什么时候一定会执行;

总结一下:

ActivityAndroid提供的应用程序架构,它规定了一个应用运行的框架,它的生老病死;负责它的基础设施的创建和销毁,以及各个activity之间的切换,状态管理等;

有了这些规定,每个应用开发者,不需要关心进程的创建,不需关心主循环,比如你不会在apk包里面看到main函数,你也不会在apk包里面看到有关主循环的东西,你也不需要关心你的程序如何被暂停,如何被关闭等等,只需要按照它规定的接口写,就万事俱备;这些接口也很简单,也就是onCreateonStartonResume,onPauseonResume,onRestart,onStop,onDestory,这些接口也不是都需要实现的,后面会再讲。

大家来看一看Android实现的各种activity

2Activity的启动与关闭

一个Android应用通常是会包含多个Activity的,但是只有一个Activity会作为程序的入口,其他的Activity要不就是有入口Activity启动,要不就是有入口Activity启动的Activity启动。

Activity启动其他Activity的方式有两种:

startActivityIntent intent:启动其他Activity

startActivityForResultIntentintent, int requestCode:以制定请求码(requestCode)启动Activity,而且程序将会等到新启动Activity的结果(通过重写onActivityResult(……)方法来获取)

startActivityForResult(Intent intent , intrequestCode)这个方法用于指定Activity而且期望获取指定Activity返回的结果。并且为了获取指定Activity所返回的记过,当前Activity需要重写onActivityResultInt requestCode , int resultCode , Intent intent,这其中requestCode是请求码,而resultCode就是结果码。

3、使用BundleActivity之间交换数据

Intent是两个Activity之间传递数据的信使,因此将主要的交换数据放入Intent即可实现Activity之间的数据交换

Intent提供的putExtrasBundle data)就是传递数据的关键函数,而这其中Bundle类型的data就是数据传递的关键了。

Bundle类型的数据以及可传递数据的函数:

putXxx(String key , Xxx data):向Bundle放入int long等各种类型的数据

putSerializableSstring key, Serializable data):向Bundle中放入一个可序列化的对象

而取出Bundle数据携带包里面的数据,Bundle也提供了如下方法:

getXxx(String key , Xxx data)

getSerializable(String key ,Serializabledata)

4 Activity的生命周期介绍

上面提到过,一个Activity有以下这些状态:

OnCreate,onStart,onResume,onPause,onResume,onRestart,onStop,onDestory,这些状态的切换,如下图所示:

                                   

 

OnCreate:表示这个activity已经被创建了,比如这里就可以放置你直接设置好的UI通过setContentView(View),放入到显示框架里面,它和onDestory相对;

onStart:表示activity已经启动了,如果没什么特别要做的,可以不实现,它和onStop相对;

onRestart:表示在Stop以后,但是没有被destory,这个activity再次被激活,那么将会走这个onRestart路线;

onResume:完全是为了实现在onRestart的时候而引入的,但是在第一次启动的时候也被执行;它是和onPause相对的;

onPause:它表示暂停,比如一个新的activity弹出来覆盖在旧的activity上,那么旧的activity将会先进入pause状态;

onStop:如果新的activity弹出来后完全覆盖了旧的activity,那么旧的那个activity将会进入到onStop状态;

onDestory:进入Stop状态的activity会被定期清理,比如为了节省内存,比如是用户故意的配置,比如是用户通过finish系统调用,activity都会被Destory,释放掉所有的资源;

 

如果我们从launcher里面随便点击一个应用的图标A将会走这些流程:

onCreate——>onStart——>onResume

当一个新的activity B弹出来的时候,那么A activity将会走下面的流程:

onPause->onStop或者就是onPause,视新出来的activity是否完全遮住activityA

如果activity B被关闭,那么如果这时候A处于pause状态,那么它就简单的执行onResume;如果它处于onStop,那么它会执行onRestart,onStart,onResume;

也就是说,一个activity的启动,肯定会走onStartonResume;当这个activity资源已经释放了,要重新启动,那么才会执行onCreate

 

从上面的结论来说,一个activityonCreate函数需要负责资源的申请,变量的初始化等;当暂停的时候需要做一些数据,状态的保存等;

Stop的时候该关闭的就关闭了,该释放的就释放,不能留到onDestory;  Android的文档上说:

在杀掉一个Activity之前,唯一一个一定会被保证执行的函数是onPause,

也就是说连onStop也不一定是可靠的,而onDestory就更不可靠了,你甚至都无法知道它什么时候将会被执行;

5Activity的状态及状态间的转换

android中,Activity 拥有四种基本状态:

Active/Runing:一个新 Activity启动入栈后,它在屏幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态。

Paused Activity被另一个透明或者 Dialog 样式的 Activity覆盖时的状态。此时它依然与窗口管理器保持连接,系统继续维护其内部状态,所以它仍然可见,但它已经失去了焦点故不可与用户交互。

Stoped Activity被另外一个 Activity 覆盖、失去焦点并不可见时处于 Stoped状态。

Killed  Activity 被系统杀死回收或者没有被启动时处于 Killed状态。

当一个 Activity 实例被创建、销毁或者启动另外一个 Activity时,它在这四种状态之间进行转换,这种转换的发生依赖于用户程序的动作。下图说明了 Activity在不同状态间转换的时机和条件:

1. Activity 的状态转换

                                    

 

如上所示,Android 程序员可以决定一个 Activity,但不能决定它的,也就时说程序员可以启动一个 Activity,但是却不能手动的结束一个 Activity。当你调用Activity.finish()方法时,结果和用户按下 BACK键一样:告诉Activity Manager Activity实例完成了相应的工作,可以被回收。随后 Activity Manager激活处于栈第二层的 Activity 并重新入栈,同时原 Activity被压入到栈的第二层,从 Active 状态转到 Paused状态。例如:从 Activity1 中启动了 Activity2,则当前处于栈顶端的是 Activity2,第二层是 Activity1,当我们调用Activity2.finish()方法时,Activity Manager 重新激活Activity1 并入栈,Activity2 Active 状态转换 Stoped状态,Activity1. onActivityResult(int requestCode, int resultCode, Intentdata)方法被执行,Activity2返回的数据通过data参数返回给 Activity1

Activity

Android 是通过一种 Activity栈的方式来管理Activity 的,一个 Activity的实例的状态决定它在栈中的位置。处于前台的 Activity 总是在栈的顶端,当前台的 Activity因为异常或其它原因被销毁时,处于栈第二层的 Activity 将被激活,上浮到栈顶。当新的 Activity启动入栈时,原 Activity 会被压入到栈的第二层。一个 Activity在栈中的位置变化反映了它在不同状态间的转换。Activity 的状态与它在栈中的位置关系如下图所示:

2. Activity 的状态与它在栈中的位置关系

                           

 

如上所示,除了最顶层即处在 Active 状态的 Activity外,其它的 Activity 都有可能在系统内存不足时被回收,一个 Activity的实例越是处在栈的底层,它被系统回收的可能性越大。系统负责管理栈中 Activity的实例,它根据 Activity 所处的状态来改变其在栈中的位置。

6、进程生命周期

Android系统会尽量久的保留应用进程。但是当内存降低时最终还是要移除旧的进程。就像Activity生命周期中描述的一样,移除哪个进程还是要取决于关联的用户与之交互的程度。一般来说,进程可以基于其中运行的activity所处的生命周期而分成四种状态,下面将这些状态根据重要程度排列。系统会在kill更重要的进程(第一个)之前首先kill那些不那么重要的进程(最后一个)。

<!--[if !supportLists]-->1. <!--[endif]-->前景activity:(处于屏幕最上方,用户与之交互的activity)被认为是最重要的。如果设备上的内存无法满足它的使用,Kill此进程只能作为最后的手段。一般来说这个时候设备处于内存paging状态,为了使用户界面保持响应才会发出这个kill请求。

<!--[if !supportLists]-->2. <!--[endif]-->可见activity:(一个对用户可见,但是不在前景的activity,比如处在浮动对话框后)被认为是非常重要的,除非为了保证前景activity运行,否则不会被kill

<!--[if !supportLists]-->3. <!--[endif]-->后台activity(一个对用户不可见,并处于paused状态的activity)就不再重要了,所以当需要为其它前景的或者可见的activity运行而回收内存时系统可以很安全的kill它们。

<!--[if !supportLists]-->4. <!--[endif]-->空进程是一个没有运行activity或者其他应用组件(比如Service或者IntentReceiver类)的进程。当内存开始降低时系统很快就会kill掉这些进程。因此当你要在activity外运行任何的后台操作时,必须在IntentReceiverService的上下文环境中运行,这样系统才知道需要将你的进程保留而不是kill

有些时候Activity可能需要长时间运行一个操作,且它并不依赖于activity的生命周期而存在。例如一个照相机应用可能允许你将照片上传到web站点。上传可能需要很长时间,在上传过程中应该允许用户离开这个应用。为了做到这一点,你的activity应该在上传时启动一个Service来执行此工作。这将使系统在你的进程上传数据的过程中能够恰当的区分它的优先级(认为此进程比其他不可见应用更重要),不管原来的activity的状态是pausedstopped还是finished

7、配置Activity

         属性设置:

   和进程相关

       taskAffinity :拥有相同的AffinityActivity通常运行在同一个task里面;比如android:taskAffinity=“android.task.browser”,一个任务的Affinity决定于它启动的root activity,默认就是包名;

       allowTaskReparenting :是否允许重新认父亲;Activity有一个特点,谁启动它的,它就认谁做父亲;如果这个flagtrue,也就是说,当和它有真正的血缘关系( taskAffinity决定)的activity起来的时候,可以认回它本来的父亲;

       process:此activity在那个进程里面运行,默认应该就是包名,如果这个名字是以’:”开头,表示需要创建一个新的进程;如果是以小写字母开头,则共享一个全局的进程名字;

       multiprocess :是否这个activity的实例运行在别的进程,true是可以,false就只能运行在定义这个activity的应用里面;

•     和显示相关

       icon :显示给用户看的图标,比如在launcher里面,我们会看到这个主activityICON,所谓主的activity是申明了一下Intentfilteractivity

      <actionandroid:name="android.intent.action.MAIN" />

    <categoryandroid:name="android.intent.category.LAUNCHER" />

       label :显示给用户看到的activity的名字,通常是以个对资源的引用,这样的话就可以保证被本地化了;

       configChanges :这个是表示你这个activity对那些配置事件感兴趣,默认的话,如果这些事件发生,将会导致这个activity重启,但是你设置了这样的属性将会触发函数onConfigurationChanged被调用,不会被重启,我们通常的设置为keyboardHidden|orientation,也就是键盘隐藏以及方向切换都不会被重启;这些属性包括:mccSIM卡插入,并且取得了MCC号码;mnc:取得了网络号;locale :用户选择了一种新的语言;touchscreen:触屏发生了变化;keyboard ,键盘类型发生了变化,比如新的键盘插入了;keyboardHidden:键盘的可访问性发生了变化,比如键盘被收起或者展开;navigation :浏览方式方式了变化,比如轨迹球,dpad等不可用了;orientation:屏幕方向变化了,比如用户旋转了手机;screenLayout :屏幕的layout方式了变化;fontScale:字体大小发生了变化;uiMode UI模式发生了变化,比如夜晚模式被启用;

       screenOrientation :这个activity需要在什么方向上显示,横屏,竖屏,还是都可以等

       theme:这个activity所用的theme

       windowSoftInputMode :软键盘输入法的显示状态,以及这个activity为这个输入法所要做的界面调整;

•     其他属性

       exported:对外是否可见,如果没有intent-filter默认为false,否则默认为true

       name activity的名字,或者为完整的类名,或者为带点的名字,这样的话,它的全称为包名加这个名字;

       noHistory :不为在ActivtiyManagerService的历史栈里面,用户浏览完离开完就销毁,无法通过back键返回;

       permission :如果调用者不具备它这里申明的权限就无法启动它;

 

 

0 0
原创粉丝点击