Activity的概念

Activity相关概念

 说明:翻译自google android开发手册,错误在所难免,欢迎指正。

 

一个activity相当于手机的一屏,它能够获得焦点,用户一般都在它上面操作。几乎所有的activity都跟用户打交道,所以Activity类主要负责创建一个窗口,而你可以通过调用setContentView(View)方法在Activity上放置你的UI组件。Activity除了通常作为一个全屏的窗口呈现给用户之外,他们还有其他的使用方法:1、作为一个浮动窗口,这可以通过设置theme属性windowIsFloatting来实现;2、嵌入其他的Activity,这使用ActivityGroup来实现。

Activity的子类通常要实现如下两个方法,也就是说,当你要自己创建一个activity的时候,一般需要实现的: 

  1. onCreate(Bundle)。我们可以在该方法里面初始化Activity。通常,我们在这个方法里面调用setContentView(int)来设置Activity的内容,这个方法的int类型的形参是一个布局资源的ID,我们在这个布局中就设计好了Activity的内容了。此外,使用findViewById(int)方法检索到我们要进行交互的widgets组件。
  2. onPause()。当用户离开当前activity的时候,我们就在这个方法里面处理,一般来说,就是处理用户所做的改变,譬如用户填写了一些数据,我们就在这个方法里提交这些数据进行保存,通常是保存到ContentProvider。

 

Activity lifecycle

在系统中,存活的Activity是用一个activity stack来进行管理的。当我们创建一个新的activity的时候,它就被存放到activity stack的最上面。而之前的一个activity(如果还存活的话)就放在当前activity的下面。只有当前的activity退出栈的时候,之前的activity才能呈现到屏幕上。

一个activity的生命周期中主要有四个状态:

  1. active(running)。这个状态表示这个activity正在屏幕的前端(存放在activity stack的栈顶)且获得焦点;
  2. paused。这个状态表示这个activity已经失去了焦点但仍然可见。当屏幕最前端不是一个满屏的activity或者是一个透明的activity的时候(获得了焦点),这时你仍然可以看到旧的activity。这个旧的activity仍然是存活的,它保存了所有的状态、成员信息,且关联到window manager。当系统内存非常紧张的时候,系统是会自动删除处于paused状态的activity的。
  3. stopped。如果一个activity已经完全被另外一个activity所覆盖,它就处于这个状态。处于stopped状态的activity仍然保留了其所有的状态、成员信息,但是它已经是不可见的了。只要系统需要(譬如内存要被使用),系统就会删除掉这个activity。
  4. 处于paused或者stopped状态的activity,系统能够通过把它的状态设置为finish,从而从内存中删除掉它相关的数据,或者直接就kill掉它的进程。如果要重新在屏幕上呈现这个activity,那么就需要重新启动这个activity并把它的状态恢复到之前的情况。

activity的生命周期

 

在上面这个图中,activity有三种生命历程:

  1. entire lifetime 。从onCreate(Bundle)一直到onDestroy()。我们在onCreate(Bundle)中做一些比较重要的工作,譬如获取资源、创建线程等,而在onDestroy()中释放仍然占用的资源。例如,如果我们的程序有一个线程从网络上下载歌曲,那么我们可以在onCreate(Bundle)中创建该线程,最后在onDestroy()中关闭掉该线程。
  2. visible lifetime。从onStart()到onStop()。在这两个方法之间的时间里,我们都能够从屏幕上看到activity,虽然它不一定在屏幕的最前端且获得焦点。在这段时间里,系统仍然是保留了其所需的资源的,直到它被系统kill掉。onStart()和onStop()是可以被多次调用的,这样子才能不断地呈现activity和隐藏activity。
  3. foreground lifetime。从onResume()到onPause()。这段时间里,activity一直是可见的。onResume()和onPause()可以是被频繁调用的,因此这两个方法中的代码必须是轻量级的。

上面这些方法就定义了activity的生命周期,我们要实现一个Activity的子类的时候通常要override这些方法,而且在override这些方法的时候通常要先调用父类的这些方法。supper.xxx()。所有的子类都要实现onCreate(Bundle)来做初始化,大部分都要实现onPause()来提交数据。

 

Configuration Changes

如果设备的配置数据(配置数据是由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)不会被调用。

 

Starting Activities and Getting Results

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。

 

Saving Persistent State

一个activity通常要处理的有两种persistent state:共享的类文档数据(一般通过content_provider存储在SQLite数据库中)和内部的state(internal state),例如user preferences。前者是可多个程序共享的,后者一般都是一个程序私有的。

 

 对于content provider data,建议activities使用一个“edit in place”用户模型。即一个用户所作的任何数据更改是立即生效的,无需用户再做一个确认的动作。支持这样一个模型通常需要遵循如下两条规则:

  1. 当创建一个新的文档,相应的后台数据库条目或文件必须立即创建。例如,当用户选择写一封邮件的时候,相应的数据库条目必须在用户开始输入数据的时候就创建以保存用户输入的数据。这样,如果用户访问其他的activity之后又返回来写邮件,那么之前写的邮件就会作为一个草稿出现,里面保存了之前用户输入的数据。
  2. 当调用一个onPause()方法的时候,就应该将用户所作的更改提交到后台的content provider或者文件中。这样子就能确保将要被运行的其他activity能看到这些数据。你可能需要在一个activity的生命周期中的关键时刻提交数据:诸如启动一个新的activity,在finish当前的activity(之后这个activity应该就被destroy了),用户切换输入焦点到另外一个输入域的时候。

当用户在多个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的一段代码:

 

Process Lifecycle

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).

  1. 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.

  2. 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.

  3. 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.

  4. An empty process is one hosting no activities or other application components (such as Service or BroadcastReceiver 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。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值