Activity概述与生命周期.docx

上传人:b****5 文档编号:3783862 上传时间:2022-11-25 格式:DOCX 页数:12 大小:176.58KB
下载 相关 举报
Activity概述与生命周期.docx_第1页
第1页 / 共12页
Activity概述与生命周期.docx_第2页
第2页 / 共12页
Activity概述与生命周期.docx_第3页
第3页 / 共12页
Activity概述与生命周期.docx_第4页
第4页 / 共12页
Activity概述与生命周期.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

Activity概述与生命周期.docx

《Activity概述与生命周期.docx》由会员分享,可在线阅读,更多相关《Activity概述与生命周期.docx(12页珍藏版)》请在冰豆网上搜索。

Activity概述与生命周期.docx

Activity概述与生命周期

Activities

Activity是这样一个程序组件,它为用户提供一个用于任务交互的画面。

例如,拨打电话,拍照,发邮件。

或者查看地图。

每一个activity都被分配一个窗口。

在这个窗口里,你可以绘制用户交互的内容。

这个窗口通常占满屏幕,但也有可能比屏幕小,并且浮在其它窗口的上面。

一个应用程序通常由多个activity组成,它们彼此保持弱的绑定状态。

典型的,当一个activity在一个应用程序内被指定为主activity,那么当程序第一次启动时,它将第一个展现在用户面前。

为了展现不同的内容,每一个activity可以启动另外一个。

每当一个新的activity被启动,那么之前的将被停止。

但系统将会把它压入一个栈(“backstack”即后退栈),当一个新的activity启动,它将被放到栈顶并获得用户焦点。

后台栈遵循后进先出的栈机制。

所以当用户完成当前页面并按下返回按钮时,它将被pop出栈(并销毁),之前的activity将被恢复。

(关于后退栈的更多讨论在任务和后退栈)

当一个activity因为另一个activity的启动而被停止,那么其生命周期中的回调方法,将会以状态改变的形式被调用。

activity通过它自身状态的改变可以收到多个回调方法。

当系统创建,停止,恢复,销毁它的时候。

并且每个回调方法都给你做相应处理工作的机会。

例如,当停止的时候,你的activity应当释放比较大的对象,例如网络连接,数据连接。

当你的activity恢复时,你可以请求必须的资源并恢复一些被打断的动作。

这些状态事务的处理就构成了activity的生命周期。

接下来将讨论如何搭建和使用activity,完整讨论activity的生命周期是怎么工作的,这样你就可以合理地管理不同activity状态间的事务处理。

创建一个Activity

要创建一个activity,你必须创建一个Activity(或者它存在的子类)的子类。

在你的子类里,你需要实现系统调用的回调方法,这些方法用于activity在生命周期中进行事务处理。

例如创建,停止,恢复,销毁。

其中两个最重要的回调方法分别为:

onCreate()

你必须实现这个方法。

系统会在创建activity的时候调用这个方法。

在实现这个方法的同时,你需要实现你activity的重要组件。

最重要的是,你必须在这里调用setContentView()来定义你activity用于用户交互的布局。

onPause()

系统将会调用这个方法作为用户离开activity的首先提示(虽然这并不意味着activity正在被销毁)。

这通常是你应该在用户会话之前提交并保存任何更改的时机。

(因为用户可能不会再回到这个activity).

你还应该会用到一些其他的生命周期回调方法,它们将帮助你在activity和可能导致你的activity停止甚至销毁之间保持流畅的用户体验。

所有的生命周期回调方法都将在后面讨论。

详细请看管理Activity的生命周期.

实现一个用户交互界面

activity的用户接口由一些View的派生类组成的层级结构提供。

每一个view控制acitivity所在window的一个特殊的矩形空间。

并且可以响应用户的交互。

例如,一个view可能是一个按钮,当用户碰触的时候将发起动作。

"Layouts"是一组继承了ViewGroup的布局。

它们为子视图提供了唯一的布局模型。

例如线性布局,表格布局,相对布局。

你也可以继承View和ViewGroup(或它们的子类)去创建你自己的组件或布局,并用它们组成activity布局。

定义布局最常用的方式是使用XML布局文件,它保存在你程序的资源中。

这种方式可以保证你的业务逻辑代码和用户交互界面分开。

你可以通过setContentView()传递布局文件的ID来设置程序UI。

当然,你也可以在activity代码里自己新建View,并通过插入子View到ViewGroup。

然后把这些视图的根视图传入到setContentView()。

更多用户界面创建请参照UserInterface文档。

在配置文件中声明activity

为了可以访问activity,你必须把它配置到配置文件中。

首先打开配置文件,在中增加一个元素。

例如:

name=".ExampleActivity"/>

...

...

你可以给这个元素加入很多其他的属性。

例如名称,图标,或者activity的主题风格。

android:

name属性是唯一用来指定acitivity名称的属性。

一旦你发布了程序,就不能改变它的名字,否则将破坏一些功能,例如程序图标。

(阅读博文查看你不能改变的属性

查阅来获得更多关于如何配置activity。

(官方文档是最好的学习资源)。

使用filter

也可以用很多来指定其他的组件怎样激活它。

当你使用AndroidSDKtools来创建一个程序,主activity将会自动包含一个被分类为"launcher"的intentfilter,如下:

name=".ExampleActivity"android:

icon="@drawable/app_icon">

name="android.intent.action.MAIN"/>

name="android.intent.category.LAUNCHER"/>

元素指定程序的入口。

指出该activity应该被列如系统的启动器(launcher)(允许用户启动它)

如果你想要你的程序更加独立,并不想让其他程序访问你的activity,那么你就不必声明intentfilter,只有一个activity应该有"main"action和"launcher"分类,例如上述例子。

你不想公开的activity应该不包含任何intentfilter.但你可以使用明确的intent来启动它们。

(下文将详述,显式与隐式启动)。

然而,如果你想要你的activity响应其他程序(或当前程序)的隐式intent,你必须为activity定义额外的intentfilter。

每一个你想响应的intent,都必须包含一个,并包含一个元素,另外,可以包含一个也可以包含一个元素。

这些元素指定了intent的类型。

关于响应intent的更多方式,请查阅Intents和IntentFilter。

启动一个Activity

你可以启动一个其他的activity通过调用startActivity(),并传递一个Intent,它用于描述acitity。

intent指定了你想要启动的activity,或者指定了你想展现的动作(系统帮你选择合适的activity,它可能来自于其他的程序)。

intent也可以携带比较小量的数据,用于启动acitivity。

在你自己的应用中,你经常会简单地启动一个已知的activity,通过创建一个明确的intent。

这个intent指定了activity的类名。

例如下面演示了如何启动一个叫SignInActivity的activity:

Intentintent=newIntent(this,SignInActivity.class);

startActivity(intent);

然而,你的程序可能想要展示某些动作,例如发邮件,短信,微博,或者使用你activity中的数据。

这时候,你就不应该使用自己的activity来做这些工作。

你应该调用系统中其他程序提供的响应功能。

这是intent真正体现其价值的地方。

你可以创建一个描述了响应动作的intent,然后系统来为你挑选完成任务的程序。

如果有多个选择,系统会提示用户进行选择。

例如你想让用户发邮件,你可以创建下面的intent:

Intentintent=newIntent(Intent.ACTION_SEND);

intent.putExtra(Intent.EXTRA_EMAIL,recipientArray);

startActivity(intent);

EXTRA_EMAIL是一个邮件intent中添加的额外字符串数组,它指定了邮件该发给哪些邮件地址。

当一个邮件程序响应了这个intent,它将读取这些地址,并把他们放置到邮件表单的被发送人栏。

这时,邮件程序被启动。

当用户完成了发送操作,你的activity会被恢复。

启动一个带返回结果的activity(单例模式的Activity无法向其他activity回调数据)

有时候,你想要启动一个activity,并从这个activty获得一个结果。

这时,要通过startActivityForResult()(取代startActivity())来启动activity。

然后通过实现onActivityResult()回调方法来获得返回后的结果。

当这个后续的activity被关闭,它将发送一个Intent给onActivityResult()方法。

例如,你可能想要取一个联系人的信息。

下面介绍怎么创建intent并处理结果:

privatevoidpickContact(){

//Createanintentto"pick"acontact,asdefinedbythecontentproviderURI

Intentintent=newIntent(Intent.ACTION_PICK,Contacts.CONTENT_URI);

startActivityForResult(intent,PICK_CONTACT_REQUEST);

}

@Override

protectedvoidonActivityResult(intrequestCode,intresultCode,Intentdata){

//Iftherequestwentwell(OK)andtherequestwasPICK_CONTACT_REQUEST

if(resultCode==Activity.RESULT_OK&&requestCode==PICK_CONTACT_REQUEST){

//Performaquerytothecontact'scontentproviderforthecontact'sname

Cursorcursor=getContentResolver().query(data.getData(),

newString[]{Contacts.DISPLAY_NAME},null,null,null);

if(cursor.moveToFirst()){//Trueifthecursorisnotempty

intcolumnIndex=cursor.getColumnIndex(Contacts.DISPLAY_NAME);

Stringname=cursor.getString(columnIndex);

//Dosomethingwiththeselectedcontact'sname...

}

}

}

这个例子展示了使用onActivityResult()来获取结果的基本方法。

第一步要判断请求是否被成功响应,通过判断resultCode是不是RESULT_OK—,然后判断这个响应是不是针对相应的请求—,此时只要判断requestCode和发送时提供的第二个参数startActivityForResult()是否相匹配。

最后,查询Intent中的data信息。

(data参数)。

这个过程中,ContentResolver开启了一个查询而不是contentprovider,它返回一个Cursor,这将允许数据被读取。

更多contentprovider相关信息,请查阅ContentProviders文档。

关于intent的更多信息,查看IntentsandIntentFilters文档。

关闭Activity

你可以通过调用finish()来终止activity。

你也可以调用finishActivity()来终止你之前启动了的一个独立activity。

注意:

多数情况下,你不应该明确地通过这些方式来关闭acitivity。

就像下面要讨论的activity的生命周期。

系统会为你管理。

所以你不必关闭他们。

调用这些方法将有悖于用户体验。

它们仅用于你绝对不想让用户再返回这个activity的实例。

管理activity的生命周期

通过实现回调方法来管理你的activity的生命周期,对于开发一个健壮而又灵活的应用程序而言是至关重要的。

与其它activity的关联性、自身的任务和backstack直接影响着一个activity的生命周期。

activity可能处于三种基本的状态:

Resumed:

activity在屏幕的前台并且拥有用户的焦点。

(这个状态有时也被叫做“running”。

Paused:

另一个activity在前台并拥有焦点,但是本activity还是可见的。

也就是说,另外一个activity覆盖在本activity的上面,并且那个activity是部分透明的或没有覆盖整个屏幕。

一个paused的activity是完全存活的(Activity对象仍然保留在内存里,它保持着所有的状态和成员信息,并且保持与windowmanager的联接),但在系统内存严重不足的情况下它能被杀死。

Stopped:

本activity被其它的activity完全遮挡住了(本activity目前在后台)。

一个stopped的activity也仍然是存活的(Activity对象仍然保留在内存中,它保持着所有的状态和成员信息,但是不再与windowmanager联接了)。

但是,对于用户而言它已经不再可见了,并且当其它地方需要内存时它将会被杀死。

如果activity被paused或stopped了,则系统可以从内存中删除它,通过请求finish(调用它的finish()方法)或者直接杀死它的进程。

当这个activity被再次启动时(在被finish或者kill后),它必须被完全重建。

实现生命周期回调方法

当一个activity在上述描述的状态之间转换时,它将通过各种回调方法来获得通知。

所有的回调方法都是钩子(hook),当activity状态发生改变时你都可以重写这些方法来执行对应的工作。

以下的activity提纲包含了所有基本的生命周期方法:

publicclassExampleActivityextendsActivity{

@Override

publicvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

//Theactivityisbeingcreated.

}

@Override

protectedvoidonStart(){

super.onStart();

//Theactivityisabouttobecomevisible.

}

@Override

protectedvoidonResume(){

super.onResume();

//Theactivityhasbecomevisible(itisnow"resumed").

}

@Override

protectedvoidonPause(){

super.onPause();

//Anotheractivityistakingfocus(thisactivityisabouttobe"paused").

}

@Override

protectedvoidonStop(){

super.onStop();

//Theactivityisnolongervisible(itisnow"stopped")

}

@Override

protectedvoidonDestroy(){

super.onDestroy();

//Theactivityisabouttobedestroyed.

}

}

注意:

实现这些生命周期方法时,必须保证在其它代码之前首先调用一下父类的方法,如上例所示。

总体来讲,这些方法定义了一个activity的完整的生命周期。

通过实现这些方法,你可以监控activity生命周期中三个嵌套的循环:

activity的完整生存期会在onCreate()调用和onDestroy()调用之间发生。

你的activity应该在onCreate()方法里完成所有“全局global”状态的设置(比如定义layout),而在onDestroy()方法里释放所有占用的资源。

例如,如果你的activity有一个后台运行的线程,用于从网络下载数据,那么你应该在onCreate()方法里创建这个线程并且在onDestroy()方法里停止这个线程。

activity的可见生存期会在onStart()调用和onStop()调用之间发生。

在这期间,用户可在屏幕上看见这个activity并可与之交互,但是没有获取焦点。

例如,当一个新的activity启动后调用了onStop()方法,则这个activity就无法被看见了。

在这两个方法之间,你可以管理那些显示activity所需的资源。

例如,你可以在onStart()方法里注册一个BroadcastReceiver用于监控影响用户界面的改动。

并且当用户不再看到你的显示内容时,在onStop()方法里注销掉它。

系统会在activity的整个生存期内多次调用onStart()和onStop(),因为activity可能会在显示和隐藏之间不断地来回切换。

activity的前台生存期会在onResume()调用和onPause()之间发生。

在这期间,activity是位于屏幕上所有其它的activity之前,并且拥有用户的输入焦点。

activity可以频繁地进入和退出前台——例如,当设备进入休眠时或者弹出一个对话框时,onPause()就会被调用。

因为这个状态可能会经常发生转换,为了避免切换迟缓引起的用户等待,这两个方法中的代码应该相当地轻量化。

图1说明了activity在状态之间可能行走的这些循环和路径。

矩形代表了你可以实现的回调方法,用于activity状态转换时执行相应操作。

图1.activity生命周期

同样的生命周期回调方法已经在表1中列出了,该表更详细地描述了每个回调方法,并且指明了每个方法在activity的全生命周期中的位置,包括回调方法完成后系统是否会杀死这个activity。

标为“之后可否被杀死?

”的列指明了系统是否可以在这个方法返回之后的任意时刻杀掉这个activity的宿主进程,而不再执行其它流程上的activity代码。

有三个方法是标为“可以”:

(onPause()、onStop()、和onDestroy())。

因为onPause()是三个方法中的第一个,一旦activity被创建,onPause()就是进程可以被杀死之前最后一个能确保被调用的方法——如果系统在某种紧急情况下必须回收内存,则onStop()和onDestroy()可能就不会被调用了。

因此,你应该使用onPause()来把至关重要的需长期保存的数据写入存储器(比如用户所编辑的内容)。

不过,应该对必须通过onPause()方法进行保存的信息有所选择,因为该方法中所有的阻塞操作都会让切换到下一个activity的停滞,并使用户感觉到迟缓。

“之后可否被杀死?

”列中标为“否”的方法,在它们被调用时的那一刻起,就会保护本activity的宿主进程不被杀掉。

因此,只有在onPause()方法返回时至onResume()方法被调用时之间,activity才会被杀掉。

直到onPause()再次被调用并返回时,activity都不会再次允许被杀死。

Note:

表1中标明的技术上不“可杀”的activity仍然有可能会被系统杀死——但那只有在没有任何资源的极端情况下才会发生。

什么时候activity会被杀掉,已在文档进程和线程里详细说明了。

保存activity的状态(onSaveInstanceState何时调用)

管理Activity生命周期一节中已简单提到,当一个activity被paused或者stopped时,activity的状态可以被保存。

的确如此,因为Activity对象在paused或者stopped时仍然被保留在内存之中——它所有的成员信息和当前状态都仍然存活。

这样用户在activity里所作的改动全都还保存着,所以当activity返回到前台时(当它“resume“),那些改动仍然有效。

不过,如果系统是为了回收内存而销毁activity,则这个Activity对象就会被销毁,这样系统就无法简单地resume一下就能还原完整状态的activity。

如果用户要返回到这个activity的话,系统必须重新创建这个Activity对象。

可是用户并不知道系统是先销毁activity再重新创建了它的,所以,他很可能希望activity完全保持原样。

这种情况下,你可以保证activity状态的相关重要信息都由另一个回调方法保存下来了,此方法让你能保存activity状态的相关信息:

onSaveInstanceState()。

在activity变得很容易被销毁之前,系统会调用onSaveInstanceState()方法。

调用时系统会传入一个Bundle对象,你可以利用putString()之类的方法,以键值对的方式来把activity状态信息保存到该Bundle对象中。

然后,如果系统杀掉了你的application进程并且用户又返回到你的activity,系统就会重建activity并将这个Bundle传入onCreate()和onRestoreInstanceState()中,你就可以从Bundle中解析出已保存信息并恢复activity状态。

如果没有储存状态信息,那么传入的Bundle将为null(当activity第一次被创建时就是如此)。

注意:

activity被销毁之前,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1