Activity和Task的设计思路和方法

bentengdehe 2012-03-29

      Activity和 Task是 Android Application Framework架构中最基础的应用,开发者必须清楚它们的用法和一些开发技巧。本文用大量的篇幅并通过引用实例的方式一步步深入全面讲解它们的基础原理(underlying principles)和架构(mechanisms),例如Navigation Multitasking、activity re-use、intents和 activity stack等„大部分与其相关的应用模块。重点讲解开发过程中如何更准确的体现用户交互性的便捷和高效,同时也帮助分析Designers和 Developers在开发期间所要面对的问题。文中涉及到的实例有一部分是属于平台自带的 application(例如:拨号程序等),另外也有 Google产品线中的一些有代表性的应用(例如:Google Map等)。建议大家亲自利用 Emulator或者 Android-powered device测试实例中的效果,这样可以帮助更加清晰的理解一些模块的含义。(注意:可能会因为硬件对于某些功能无法提供支持,所以有一些实例可能无法在你的测试机中正常浏览) 。

首先需要清楚一些基础模块: 

——Applications 

——Acitivities 

——Activity Stack 

——Tasks 

~~~Applications 

任何一个Android Application基本上是由一些Activities组成,当用户与应用程序交互时其所包含的部分Activities具有紧密的逻辑关系,或者各自独立处理不同的响应。这些 Activities捆绑在一起成为了一个处理特定需求的Application, 并且以“.apk”作为后缀名存在于文件系统中。Android平台默认下的应用程序 例如:Email、Calendar、Browser、Maps、Text Message、Contacts、Camera和Dialer等都是一个个独立的Apps。 

~~~Activities 

上边已经提到 Activities是构成 Applications的主要组成部分,其实可以更为具体的理解为Application仅仅是一个抽象的标签,它将系统内一部分Activities关联在一起,协同完成用户的特定需求。安装Application的过程也可以简单理解为将其所包裹的Activities导入到当前的系统中,如果系统中已经存在了相同的Activities,那么将会自动将其关联,而不会重复安装相同的 Activities,避免资源的浪费。Application卸载的过程也会检查当前所关联的Activities是否有被其它 Application标签所关联,如果仅仅是提供当前的Application使用,那么将会彻底被移除,相反则不做任何操作。 

用户与 Application的交互行为大部分都是通过 GUI来完成,在 Android平台可以有两种方式定义 GUI,其中可以利用 XML来预置静态的 GUI元素,或者在 Activity类的内部动态定义 GUI元素。这两种不同的方法都是由Activity作为驱动和响应用户交互事件的主体。当启动Application之后,至少需要一个包含有 GUI信息的 Activity实例被创建。 

Activity的主体包括两个主要部分,其中一个是 Content(data),另外一个是响应用户交互事件的行为。列举一个 Dialer例子的截图,其中包括四个部分:Dialer主界面、通讯录、查看联系人信息和添加新联系人。 

Activity和Task的设计思路和方法

下面列举了更多比较有代表性的Applications和其所包含的 Activities: 

——Email– activities to view folders, view list of messages, view a message, compose a message, and set up an account 

——Calendar– activities to view day, view week, view month, view agenda, edit an event, edit preferences, and view an alert  

——Camera– activities for running the camera, viewing the list of pictures, viewing a picture, cropping a picture, running the camcorder, viewing the list of movies, and viewing a movie  

——Game– one activity to play the game, typically another for setup 

——Maps– one activity to view a location on a map, a second for lists (such as turn list or friend list), and a third for details (friend location, status, photo)  

Application基本上是由四个模块组成:Activity、Service、Content Provider 和 Broadcast Receiver,其中Activity是实现应用的主体。 

~~~Activity Stack 

 操作应用程序时,有时需要调用多个Activities来完成需求,例如:发送邮件程序,首先是进入邮件主界面,然后启动一个新的 Activity用于填写新邮件内容,同时可以调出联系人列表用于插入收件人信息等等。在这个操作过程中 Android平台有一个专门用于管理Activities堆栈的机制,其可以方便的线性记录 Activities实例,当完成某个操作时,可以通过这个导航功能返回之前的Activity(通过按操作台的“Back”)。 

每次启动新的 Activity都将被添加到 Activity Stack。用户可以方便的返回上一个 Activity直到 Home Screen,到达Home Screen后,将无法再继续查看堆栈记录(俗话说:到头了- Androidres.com)。如果当前 Task被中止(Interrupting the task),返回到系统主界面后启动了其它操作,当希望返回到前一个 Task继续执行时,只需要再次通过主界面的Application launcher或者快捷方式启动这个 Task的 Root Activity便可返回其中止时的状态继续执行。 

相对于 Views、Windows、Menus和Dialogs而言,Activity是唯一可被记录在History stack中的数据,所以当你所设计的应用程序需要用户由A界面进入到次一级界面B,当完成操作后需要再次返回A,那么必须考虑将A看作为Activity,否则将无法从历史堆栈中返回。 

~~~Tasks 

 在 Android平台上可以将 Task简单的理解为由多个 Activities共同协作完成某一项应用,而不管 Activities具体属于哪个Application。通过下边的图示可以更清晰的理解 Applications、Tasks、Activities三者之间的关系 

Activity和Task的设计思路和方法

Activities可以被看作为是独立存在于系统资源中,而且是作为实现具体应用的主体,Task将一些 Activity关联起来实现一个更复杂的应用,单独或者多个 Tasks可以被定义为一Application。 通常实现一个 Task都会存在一个Root Activity,但并不是所有情况都如此,通过Application launcher、Home screen 的快捷方式或者 由 “Recent Tasks”(长时间按住 Home键) 最近使用过的 Task记录中启动。当从一个 Activity中启动另外一个Activity时,Back键将作用于返回前一个Activity,与此同时新开启的Activity将被添加到 Activity Stack中。 

~~~Interrupting the Task 

这是 Task一个非常重要的特性,用户可以实时中止当前为完成的 Task,新开启一个不同的 Task,当新 Task完成操作后,依然可以返回当上一次中止的 Task继续完成余下操作。这个特性大大方便了同时运行多个Tasks,并且可以方便的在他们之间切换。这里有两种方式可以从当前 Task跳转为其它 Task(应用这两种方式切换 Task,都允许返回到 Task最初中止前的状态)。 

——系统抛出一个 Notification,当前 Task会被终止,跳转为Notification的 Task。 

——用户强制中止 

当然,除了这两种方式以外,还有另外一个特殊情况,算作为第三种方式来启动一个新的 Task:Activity本身被定义为一个 Task。例如: Maps和Browser就是属于第三种情况的 Application,通过邮件中的一个地址来启动 Maps Activity作为一个新的 Task,或者通过邮件中的链接启动 Browser来启动一个新的 Task。当处在这种情况下,Back按键被触发后,将返回到上一个 Task(邮件),因为这些新的 Tasks并不是通过 Home Screen中的 Application launcher或者快捷方式来启动。 

了解 Activities和 Tasks的基本原理 

下面将通过一些有代表性的实例了解关于 Applications、Activities、Activities stack、Tasks和 Intent等一些模块的最基本原理。从各个角度分析系统对于用户在不同模式下操作的反应原理。 

 从 Home启动一个 Activity 

绝大部分的Application都由此启动(也有一些Application是通过其它 Application启动)。具体的方式有两种,其一是从系统的Application Launcher启动,另一种是直接由Home Screen的快捷方式。启动Application后,Root Activity会显示在当前窗口,并可直接供用户操作界面元素。官方给出了一个有关这个过程的图示,大体的过程是由Home下启动 Email Application,在这个应用程序中可以直接提供给用户操作的是 List Messages Activity,Home Activity切换为后台运行。 

Activity和Task的设计思路和方法

应用 Back或 Home键离开当前 Activity的区别 

应用 Back或者 Home都可以离开当前Activity(基于Application的 Root Activity),Home activity重新切换到 foreground,然而二者最根本的区别在于用户是否还需要保留当前Activity的 state。

~~~Back: 

将会终止(Destroy)当前正在运行的 Activity,返回到之前的Activity(如果是 Root Activity,那么将会直接返回到 Home Activity)。官方给出了一个相关过程的图示,当用户正在操作 List Messages Activity时,下拉邮件列表(改变了 Scrolling状态),通过 Back键返回到Home Activity之后,当再次通过 Email Icon启动 List Messages Activity时,将会看到列表处在初始位置。通过这个演示可以了解到通过 Back键离开当前Activity时,无法暂时保留住其 State数据,当再次启动时相当于重新创建了一个实例。 

Activity和Task的设计思路和方法

~~~Home: 

利用Home取代 Back返回的方式,当前 Activity将被切换到Background,而不是被 Destroied。这样的好处是可以暂时保留这个 Activity的 State信息,当再次通过Application launcher或者快捷方式启动时,可以返回到最后离开的状态。对比在 Back中引用的例子,当再次由Home返回到Activity时,将会看到最后一次操作所记录的 Scroll状态,而不是默认的初始位置。 

Activity和Task的设计思路和方法

 Exception(例外情况) 

前边列举了两种典型的情况,同时还存在一些例外的情况,某些Activity从 Background被“召唤”到foreground之后依然是相当于重新创建了新实例,其又区别于前边所论述的结果。即便是暂时保存在Background模式下(没有被Destroied),其 State数据也将丢失。例如:Contacts 和 Gallery 等。当用户启动了 Contact应用程序,并点选某个条目查看详细信息,如果通过Home键返回后,再次重复启动 Contact应用程序时,看到的并不是之前所打开的特定条目的详细信息,而是初始的默认界面。这个例子说明不是所有情况下通过Home键返回后都可以保存当前Activity的 State信息。 

另外一种是与 Back键有关的特殊情况。前边提及到大部分的 Activity通过 Back键返回到 Home Activity时,其自身将被彻底销毁,默认情况下 Activity响应 Back按键的方法被定义了Destroy行为。但对于某些特别情况,开发者可以根据需求将相应 Back按键事件的行为重新“override”,撤消默认的Destroy行为。音乐播放器是与其相关的一个典型应用,当用户在播放器的 Root Activity中触发 Back按键后,转为Background模式下继续播放当前的音乐,同时 Home Activity转为 Foreground。 

Activity的复用 

在多个不同的 Applications中,当遇到有相同目的应用时,会涉及到Activity的复用性问题,这在开发过程中是一个非常普遍的情况。复用性一直被众多开发机构强调为节约成本,优化资源的最有效的机制。对于移动应用平台更加看重资源的最优化利用,复用性的应用在Android平台上无处不在,通过两个比较基础的例子来具体的说明。 

- Contacts利用 Gallery获得图像资源 

众所周知 Contacts是手机中最常用的应用程序,主要用于存储当前用户的联系人信息,其中需要包含联系人的头像信息。在Android平台中的图像信息是由 Gallery管理,所以 Contacts必然需要复用 Gallery Activity来获取相应的图像信息。 针对于 Android或者其它平台开发应用程序都需要有良好的复用性意识,这个需要贯穿于项目的整个开发过程。包括如何利用当前系统的现有资源,或者考虑到将来可能会被其它应用程序用于完成特定的需求。当用户正在调用的 Intent filter不唯一时,系统将弹出一个供用户选择的对话框,这的确是一个完美的解决方法。 

Activity和Task的设计思路和方法

- 利用 Messaging扩展 Gallery共享功能 

用户通过 Gallery查看当前系统中的图像资源,每次单独打开一幅图像资源都可以通过 Menu -> Share将当前的资源以附件形式插入新创建的 Messaging中,并且以正常发送信息的方式将其共享给收件人。如果取消当前的共享行为,只需要通过Back按键返回到 Gallery Activity。相比较前一个例子的区别在于,Message Activity完成发送或者被取消操作,其不会返回任何信息。 

Activity和Task的设计思路和方法

 以上两个例子分别讲解了利用一系列的Activities来完成某一项需求,并且它们都调用了外部的 Application资源。 

Replacing an Activity 

目前要介绍的内容是关于在不同的 Applications中,有相同 Intent filter属性的Activities可相互间替换,这对于习惯 Windows等操作系统的用户比较不容易理解。其实如果您足够细心,就可以发现之前的例子中有关于这里所提及情况。 

通常遇到这种情况发生时,一般都是因为外部具有相同功能的 Activity A 在处理问题的能力方面要优于当前Application中默认的操作行为 Activity B,系统会抛出一个可供选择的对话框,用户根据主观判断来选择最优的方式处理当前任务。通过一个比较容易理解的实例来说明整个过程,建议“动手能力强”的同学可以通过模拟器亲自尝试。 

例如:用户在当前系统下加载了最新的Phone Ringtone Activity,取名为 Rings Extended。如果用户通过Setting -> Sounds&Display -> Phone Ringtone 来设置当前的铃音属性时,将会弹出一个包含有系统默认的Phone Ringtone Activity 和最新加载的Rings Extended两种可供选择的操作应用,同时在对话框中还提供了一种可以直接启动系统默认的操作方式选项。如果用户选择了Rings Extended,那么其将会被载入当前的线程中替代原有的默认操作行为,可以根据下面的图示来增强理解。 

Activity和Task的设计思路和方法

(这张图,如果你用过android系统的手机,应该会明白了吧)

多任务同时运行(Multitasking) 

在之前的板块有专门提到关于 Home和 Back两种切换到 Home Screen的方法和它们之间的差异性,这里将会重点涉及到系统可以同时处理多个实时运行的任务。如果用户正处于某个Application A开启状态时,通过 Home按键切换回 Home Activity的同时保留了此前Application A运行的状态信息,可以开启新程序的同时,也可以再次将 Application A切换回 Foreground。 接下来通过一个有关 Map应用的实例更加具体的了解其所涵盖的过程。 

首先的起始阶段分为三个步骤:

第一步,由Application Launcher启动 Map应用程序,并且搜索一个具体的地理位置。假设当前的网络环境非常不理想,需要花费一定的时间Download地图数据。 

第二步,当系统需要花费较长时间加载当前地图信息数据时,保持当前Activity的状态,返回 Home Activity启动其它的Applicaton,地图Activity切换到 Background,而并不会中断加载进度(依然保持网络连接)。 

         注意:以上是 Activity在默认条件下的反应行为,其切换为 Background状态后直接触发       onStop()事件,开发者可以重新定义其方法。例如:强制 Activity在转为 Background状态下,终止网络连接。 

第三步,当前 Map activity已经切换到Background状态下运行,Home Activity切换到 Foreground。这时用户启动 Calender activity,其将自动转为 Foreground状态,同时获得操作焦点。 将以上三个步骤用图示的方式表述: 

Activity和Task的设计思路和方法

 最后,退出当前Calender activity返回到 Home,再次通过 Maps图标将其处在Background状态的实例切换到Foreground。 

Activity和Task的设计思路和方法

通过上边的例子看出用户通过 Application Launcher同时运行多个 Tasks,代表系统具备多任务处理机制 – Running multiple tasks。 

启动 Application的两种不同方式

每个App都需要提供至少一个 Entry point(翻译成“入口点”有点别扭,干脆保留原样)供用户或者系统调用其所关联的 Activities,Application launcher中的小图标就是每个单独 App的 Entry Point。另外 App也可以相互间通过Activity作为 Entry Point来启动,可以将App所包含的每个Activity看作为潜在的Entry point。 系统中的Phone Application同样具有两个 Entry Points:Contacts和 Dialer。下边的图示中可以了解到用户通过 Application launcher启动Contacts Activity,选择其中某一个联系人之后,调用 Dialer Activity拨打其所提供的电话号码。

Activity和Task的设计思路和方法

Intents 

在现实世界中大家每时每刻都会与周围的环境发生互动,这个互动的过程首先要确定一种意识,例如:感觉到口渴,需要水分补充。这种意识会引导自己以习惯的方式解决口渴问题,采用的方式可以多种多样,吃冰淇淋、喝水、嚼树叶等。类似于口渴的意识形态被抽象为 Intent,并将其看作是一种对象,这就是Android响应“意识”的方式。 

在 Android平台上,用户的操作行为是由各种不同的事件组成,系统会将每个事件都抽象为 Intent对象,寻找解决这项需求的具体方法。抽象的 Intent对象有两种形式,第一种是“明确”的 Intent(Explicit Intent),在初始化的时候已经为这个Intent关联了特定的Activity。第二种是“不明确”的Intent(Implicit Intent),代表这个 Intent没有明确关联 Activity,当它被抛出后,系统在众多 Activities中根据 Intent filter来寻找与其匹配的处理方法。如果存在多个结果,用户可以根据需要选择合适的处理方法。 

引用一个具体的例子,单击一个 mailto:[email protected]链接后,这个被抛出的 Intent属于 Implicit Intent ,系统抓取了解决这个 Intent的结果,将所有的结果供用户选择(Gmail或者 Email): 

Activity和Task的设计思路和方法

下边给出更多系统默认的 Intent关联列表: 

——View the list of contacts – resolves to a contact list viewer activity 

——View a particular contact – resolves to a contact viewer activity 

——Edit a particular contact – resolves to a contact editor activity 

——Send to a particular email – resolves to an email activity 

——Dial a phone number – resolves to a phone dialer activity 

——View the list of images – resolves to an image list viewer activity 

——View a particular image – resolves to an image viewer activity 

——Crop a particular image – resolves to an image cropper activity 

Intent对象包含两个元素: 

1)Action :例如 查看、编辑、拨打电话、查看图像资源等等。 

2)Data:提供给某种行为的具体数据。加工果汁饮料,需要提供水果(黑心店除外)。 

参照官网的解释:Intent Class 和 Intent Filters。 

Tasks相互间切换 

依然是应用实例来说明这个切换的过程。在这个例子中,用户编辑一个短消息,并且插入图像附件,但是在发送之前启动 Calendar,随后切换回短消息编辑界面,最后发送信息。 

1)启动第一个 Task:Messaging App,Home > Messaging > New Message > Menu > Attach > Picture。插入图片的步骤需要调用 Gallery Activity,它是一个独立的外部程序。 

Activity和Task的设计思路和方法

Activity和Task的设计思路和方法

接下来启动另外一个 Task,由于没有直接从当前的 Activity运行 Calendar,所以需要切换到Home。

2)启动另外一个 Application(Calendar):Home > Calendar 

Activity和Task的设计思路和方法

3)查看Calendar完成后,将 Messaging由 Background切换到 Foreground模式,其中还包括了添加附件,并最终发送消息。 

Activity和Task的设计思路和方法

以上是对于Android平台中两个比较核心元素: Activities和 Tasks的基本介绍。

转自:http://www.cnblogs.com/lyp3314/archive/2011/11/08/2241558.html

相关推荐