说明:翻译自google android开发手册,错误在所难免,欢迎指正。
一个activity相当于手机的一屏,它能够获得焦点,用户一般都在它上面操作。几乎所有的activity都跟用户打交道,所以Activity类主要负责创建一个窗口,而你可以通过调用setContentView(View)方法在Activity上放置你的UI组件。Activity除了通常作为一个全屏的窗口呈现给用户之外,他们还有其他的使用方法:1、作为一个浮动窗口,这可以通过设置theme属性windowIsFloatting来实现;2、嵌入其他的Activity,这使用ActivityGroup来实现。
Activity的子类通常要实现如下两个方法,也就是说,当你要自己创建一个activity的时候,一般需要实现的:
在系统中,存活的Activity是用一个activity stack来进行管理的。当我们创建一个新的activity的时候,它就被存放到activity stack的最上面。而之前的一个activity(如果还存活的话)就放在当前activity的下面。只有当前的activity退出栈的时候,之前的activity才能呈现到屏幕上。
一个activity的生命周期中主要有四个状态:
在上面这个图中,activity有三种生命历程:
上面这些方法就定义了activity的生命周期,我们要实现一个Activity的子类的时候通常要override这些方法,而且在override这些方法的时候通常要先调用父类的这些方法。supper.xxx()。所有的子类都要实现onCreate(Bundle)来做初始化,大部分都要实现onPause()来提交数据。
如果设备的配置数据(配置数据是由Resources.Configuration定义的)改变了,那么用于显示一个用户界面的相关数据要根据改变后的配置数据来更新。由于Activity是与用户交互的主要机制,所以它对于管理配置数据的改变有特殊的支持方法。
除非你指定了其他的处理方法,否则,配置数据改变(例如,屏幕方向、语言、输入设备等改变)都会导致当前的activity被销毁(处于destroyed状态),然后通过在恰当的时候调用onPause()、onStop()和onDestroy()等方法使得activity重新经历正常的一个activity的生命周期。如果activity已经处于屏幕的最前端(running)或者对于用户来说是可见的(paused),那么调用onDestroy()方法销毁这个activity之后,会再创建这个activity的一个新的实例,创建的时候使用的是旧的activity通过onSaveInstanceState(Bundle)方法创建产生的savedInstanceState。
之所以要这么处理activity,是因为任何应用程序资源,包括布局文件,都有可能被改变。管理配置数据的唯一的安全的方式是重新检查所有的资源——layouts、drawables和strings。因为activity知道怎样保存它们的状态并根据这个状态重新创建它们的实例,因此,使得一个activity根据新的配置数据重新启动并恢复到之前的状态是一个简便的方法。
在某些特殊的情况下,可能有多种类型的配置数据被更改,譬如layouts和drawable都被更改,所以你必须同时针对这多种类型的配置数据更改情况进行处理,这用到了manifest中的android:configChange属性。如果你要管理某一种类型的配置数据更改,就需要调用当前activity的onConfigurationChanged(Configuration)方法(在这个方法里填写处理相应配置数据被更改的情况?需要确认。),这样就不用重启activity了。如果某一种类型的配置数据更改不是你说明要管理的,那么仍然会重启activity,而onConfigurationChanged(Configuration)不会被调用。
startActivity(Intent)方法启动一个新的activity,Intent参数描述了将要启动的这个activity。有时当一个activity结束的时候,你想获得它结束时返回的结果。譬如,你启动一个有contacts列表的activity,用户选择一个人之后这个activity就结束了,而你想知道用户选择的结果。为了实现这个功能,需要调用startActivityForResult(Intent,int)方法,然后通过调用onActivityResult(int,int,Intent)获得返回结果。
一个activity退出的时候,它可以通过setResult(int)返回结果给它的parent(这个parent是创建它的那个activity?是的。)。activity总是必须提供给一个结果代码的,这个结果代码可以是标准的代码——RESULT_CANCELED,RESULT_OK等,也可以是自定义的值,这个值是从RESULT_FIRST_USER开始的。此外,它还可以将其他数据包含在一个Intent实例中返回。
如果一个child activity因为某些原因而失败,譬如crashing,那么parent activity都会收到一个RESULT_CANCELED。
一个activity通常要处理的有两种persistent state:共享的类文档数据(一般通过content_provider存储在SQLite数据库中)和内部的state(internal state),例如user preferences。前者是可多个程序共享的,后者一般都是一个程序私有的。
对于content provider data,建议activities使用一个“edit in place”用户模型。即一个用户所作的任何数据更改是立即生效的,无需用户再做一个确认的动作。支持这样一个模型通常需要遵循如下两条规则:
当用户在多个activity之间切换的时候,“edit in place”这个模型就能够确保数据不丢失,也允许系统在必要的时候安全地kill掉一个至少处于paused状态的activity(前面说过,当系统内存紧张的时候系统会删除一些处于paused、stopped状态的activity)。要注意的是,用户在当前activity按下BACK时,只是离开当前activity,不是cancel,所以当前activity的内容仍然是需要保存的。取消用户所作的更改需要通过其他机制来实现,例如显示提供“revert”或者“undo”按钮。
下面是多个activity之间调用或者传播数据的主要方面,完整的信息请查看content package。
Activity类提供了一个API来管理跟一个activity关联的internal persistent state。internel persistent state主要指用户自己设定的一些参数,譬如用户查看日历时的初始界面是day view还是week view,用户浏览器的主页(home page)等。这个API就是getPreference(int),它能够检索和修改跟一个activity关联的name/value对集合。要使用在多个应用程序组件(activities、receivers、services、providers)之间共享的preferences,要使用内置的Context.getSharedPreference()方法来检索一个特定名称的preferences对象。注意,在多个application packages之间共享设置数据(preference对象)是不可以的,如果要这样做,需要使用一个content provider。
下面是一个calendar activity存储它的preferred view mode的一段代码:
Android系统尽可能地保存对程序的process,但当内存紧张的时候就需要移除旧的process。根据在Activity Lifecycle中描述的,系统决定移除哪一个process是跟用户对它的交互状态密切相关的。通常,一个process有四个状态,这儿根据其重要性列出。The system will kill less important processes (the last ones) before it resorts to killing more important processes (the first ones).
The foreground activity (the activity at the top of the screen that the user is currently interacting with) is considered the most important. Its process will only be killed as a last resort, if it uses more memory than is available on the device. Generally at this point the device has reached a memory paging state, so this is required in order to keep the user interface responsive.
A visible activity (an activity that is visible to the user but not in the foreground, such as one sitting behind a foreground dialog) is considered extremely important and will not be killed unless that is required to keep the foreground activity running.
A background activity (an activity that is not visible to the user and has been paused) is no longer critical, so the system may safely kill its process to reclaim memory for other foreground or visible processes. If its process needs to be killed, when the user navigates back to the activity (making it visible on the screen again), its onCreate(Bundle)
method will be called with the savedInstanceState it had previously supplied in onSaveInstanceState(Bundle)
so that it can restart itself in the same state as the user last left it.
An empty process is one hosting no activities or other application components (such as Service
orBroadcastReceiver
classes). These are killed very quickly by the system as memory becomes low. For this reason, any background operation you do outside of an activity must be executed in the context of an activity BroadcastReceiver or Service to ensure that the system knows it needs to keep your process around.
有时候,一个Activity可能需要一个长时间的操作,这个操作独立于activity本身的生命周期而存在。譬如,一个camera程序,允许用户上载一张相片到一个站点。上载一张图片可能需要很长的时间,但程序应该允许用户离开这个应用程序,而它仍然运行。为了实现这样的功能,你的程序就应该使用到了service。