- Android移动应用开发实用教程
- 夏辉
- 3513字
- 2025-02-23 16:00:37
2.1 Activity
Activity是Android的核心类。Activity使用Views(视图控件)去构建UI(用户图形界面)来显示信息和响应用户的行为。就桌面开发而言,一个Activity相当于一张Form,就Web程序而言相当于一个页面。本节主要从三个方面介绍Activity:Activity简介、Activity运行状态和生命周期,以及Activity的窗口显示风格。
2.1.1 Activity简介
每个Activity都有一个窗口,默认情况下,这个窗口是充满整个屏幕的。当然,也可以根据需要把窗口大小设置成比手机屏幕小,或者悬浮在其他窗口的上面。
Activity是用户和应用程序交互的接口,是一个控件的容器。在一个Activity中,可以放置很多由View及其子类组成的可视化控件,例如按钮、图像和文本框等,这些控件根据XML布局文件中指定的位置在窗口中进行摆放。一个Activity通常展现为一个可视化的用户界面。例如,一个Activity可以是系统登录界面;另外一个Activity可以是显示已登录用户信息的列表。虽然这些Activity一起工作,共同组成了一个应用程序,但每一个Activity都是相对独立的。每一个Activity都是android.app.Activity的子类。一个应用程序可能由一个或多个Activity组成,Android平台通过Activity栈来对Activity进行管理。
一个应用程序包含几个Activity及各个Activity完成什么样的功能完全取决于应用程序的设计。通常每个应用程序都包含一个在应用程序启动后第一个展现给用户的Activity。在当前展现给用户的Activity中启动一个新的Activity,就可以实现从一个Activity转换到另外一个Activity。
下面是创建Activity的示例。
【例2-1】Example2-1 Activity创建示例。
创建一个新的Android项目Example2-1 Activity01,默认情况下已经自动创建了一个Activity,项目建立后在其中的Src文件夹中可以找到创建的Activity类,默认名称为MainAc-tivity.java。详细内容请参考项目Example2-1 Activity01源代码。程序主要代码内容如下。
MainActivity类继承了Activity类(android.app.Activity),在新建的Activity类中需要复写onCreate()方法。
如果在开发环境中更新SDK Tools为Android SDK Tools 22.6.2,新建android工程时为了版本兼容,默认继承了ActionBarActivity类不是Activity,如果新建项目时最低版本选择4.0以上的SDK,就不会出现此情况。
Activity作为Android系统中一个非常重要的组件,需要在全局配置文件Manifest中进行声明,每个Android应用项目都会有自己的全局配置文件,该文件包含了组成应用程序的每一个组件(活动、服务、内容提供器和广播接收器)的结点,并使用Intent过滤器和权限来确定这些组件之间,以及这些组件和其他应用程序是如何交互的。本实例项目的全局配置文件AndroidManifest.xml的主要代码内容如下。
代码由一个根manifest标签构成,该标签通常带有一个设置项目包的package属性,一个定义Android命名空间的xmlns:android属性。
在AndroidManifest.xml中包含了一个且只能有一个Application结点,它使用各种属性来指定应用程序的各种元数据(包括标题、图标和主题)。它还可以作为一个包含了活动、服务、内容提供器和广播接收器标签的容器,用来指定应用程序组件。
应用程序显示的每一个Activity都要求有一个activity标签,并使用android:name属性来指定类的名称,使用android:label属性来指定应用程序的名称。
AndroidManifest.xml中必须包含核心的启动Activity和其他所有可以显示的屏幕或者对话框。启动任一个没有在Manifest文件中定义的Activity时,都会抛出一个运行时异常。每一个Activity结点都允许使用intent-filter子标签来指定哪个Intent启动该活动。
2.1.2 Activity运行状态和生命周期
1.Activity的3种状态
Activity有3种状态,分别是运行状态、暂停状态和停止状态。
●运行状态:当Activity在屏幕的最前端(位于当前堆栈的顶部)时,它是可见的、有焦点的。可以用来处理用户的操作(单击、双击或长按等),那么就称为激活或运行状态。值得注意的是,当Activity处于运行状态时,Android会尽可能地保持它的运行,即使出现内存不足等情况,Android也会先杀死堆栈底部的Activity,确保运行状态的Activity正常运行。
●暂停状态:在某些情况下,Activity对用户来说仍然是可见的,但不再拥有焦点,即用户对它的操作是没有实际意义的。在这个时候,它就属于暂停状态。例如,当最前端的Activity是透明或者没有全屏,那么下层仍然可见的Activity就是暂停状态。暂停的Activity仍然是激活的(它保留着所有的状态和成员信息,并保持与Activity管理器的连接),但当内存不足时,可能会被杀死。
●停止状态:当Activity完全不可见时,它就处于停止状态。但仍然保留着当前状态和成员信息。然而,这些对用户来说都是不可见的,同暂停状态一样,当系统其他地方需要内存时,它也有被杀死的可能。
2.Activity的生命周期
Activity状态的变化是人为操作的,而这些状态的改变也会触发一些事件,称为生命周期事件。这些事件分别由以下7个生命周期函数实现。
●onCreate():当创建Activity时被调用,主要完成一些初始化工作,例如设置布局文件,对按钮绑定监听器,以及加载savedInstanceState参数等。
●onStart():当Activity被用户可见时调用。
●onRestart():重启Activity时调用,该活动仍在栈中,而不启动新活动。
●onResume():Activity开始与用户交互时调用,即该Activity获得了用户的焦点(无论是启动还是重新启动一个活动,该方法总是被调用)。
●onPause():Activity被暂停或收回CPU和其他资源时调用,该方法用于保存活动状态。
●onStop():Activity被停止并转为不可见状态时调用,如果第2个Activity没有完全遮挡第1个Activity,则不调用。
●onDestroy():Activity被完全从系统内存中移除时调用。7个生命周期函数相互之间的关系和相互转换规则如图2-1所示。
图2-1 Activity的7个生命周期函数的关系转换图
为了更好地理解图2-1,下面是演示Activity生命周期函数的示例。
【例2-2】Example2-2 Activity生命周期函数示例。
1)创建项目文件Example2-2Activity02,然后在Src中分别创建两个Activity:FirstAc-tivity.java和SecondActivity.java,如图2-2所示。
2)在resource→layout中分别创建两个Activity对应的布局文件,并且编辑项目的全局配置文件AndroidManifest.xml声明这两个Activity组件。
3)编写两个Activity类文件,详细内容请参考项目Example2-2 Activity02源码。
FirstActivity.java的主要代码如下。
图2-2 创建Example2-2 Activity02项目
【代码说明】
●第07行实现把按钮对象与按钮控件绑定。
●第09行实现在按钮对象上添加监听器。
●第11行实现监听器接口。
●第1416行实现创建Intent对象,并把Intent对象传递给第2个Activity。
●第1821行实现Activity被暂停或收回CPU和其他资源时调用的方法。
●第2225行实现重新启动Activity时调用的方法。
●第2629行实现Activity开始与用户交互时的方法。
●第3033行实现当Activity被用户可见时调用的方法。
●第3437行实现当Activity被停止并转为不可见状态时调用的方法。
●第3841行实现Activity被完全从系统内存中移除时调用的方法。
SecondActivity.java主要代码如下。
4)在虚拟机中运行应用程序,启动后如图2-3a所示,利用Android中的logcat工具,可以得到程序的log信息,如图2-4所示。在图2-4中,logcat中的前3行为启动应用程序后,即图2-3a展现在用户面前时应用程序输出的信息内容。
图2-3 两个Activity效果图
a)第1个Activity b)第2个Activity
然后单击“切换到第2个Activity”按钮,启动第2个Activity,即图2-3b展现在用户面前时应用程序输出信息为logcat中的第0408行信息内容。
按“返回”按钮,使应用程序由第2个Activity回到第1个Activity,这时logcat输出第0914行信息内容。
在单击“返回”按钮关闭应用程序时,logcat将输出第1517行信息内容。
通过本项目运行的结果,可以验证各个周期函数的功能及它们互相之间的转换规则,具体如下。
1)启动Activity:系统会先调用onCreate()方法,然后调用onStart()方法,最后调用onResume()方法,Activity进入运行状态。
图2-4 Activity生命周期函数执行信息
2)当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause()方法,暂停当前Activity的执行。
3)当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume()方法,再次进入运行状态。
4)当前Activity转到新的Activity界面或按“Home”键回到主屏,自身退居后台:系统会先调用onPause()方法,然后调用onStop()方法,进入停滞状态。
5)用户按“后退”键回到原来的Activity:系统会先调用onRestart()方法,然后调用onStart()方法,最后调用onResume()方法,再次进入运行状态。
6)当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,如果系统内存不足,即杀死被覆盖的Activity。当用户按“后退”键回到这个Activity,系统再次调用onCreate()方法、onStart()方法和onResume()方法,Activity再次进入运行状态。
7)用户退出当前Activity:系统先调用onPause()方法,然后调用onStop()方法,最后调用onDestory()方法,结束当前Activity。
2.1.3 Activity窗口显示风格
默认情况下,一个Activity占据整个屏幕,这是最常见的App风格。然而有时为了突出对用户的提示等作用,可以把一个Activity设置为一个“对话框”风格,这样,它就能像一个浮动的对话框一样显示出来。
从代码的编写角度,“对话框”风格的Activity与一般的Activity没有什么区别,唯一的区别就是在AndroidManifest.xml文件中,注册Activity时,在<activity></activity>间加上:android:theme="@andriod:style/Theme.Dialog"即可实现对话框风格的Activity。
以2.1.2节中的项目为例,如果把AndroidManifest.xml文件进行修改,主要代码如下。
【代码说明】
●第0609行为Activity的IntentFilter,其中该IntentFilter的Action为Android.intent.action.MAIN,Category为Android.intent.category.LANUCH-ER。
●第1115行为第2个Activity注册的信息,包括名称、标签和样式。
重新运行项目程序,在第1个Activity中单击“切换到第2个Activity”按钮,启动第2个Activity的效果如图2-5所示。
与2.1.2节运行结果不同的是:当启动第2个Activity时,依次执行第1个Activity的onPause()方法,以及第2个Activity的onCreate()方法、onStart()方法和onResume()方法。第1个Activity虽然失去焦点,但仍然可见,所以不会执行第1个Activity的onStop()方法。而单击“返回”按键时,依次执行第2个Activity的onPause()方法、第1个Activity的onResume()方法。读者可以自行验证。
图2-5 对话框风格的Activity
如果要设置成其他的窗口显示风格,只要把上面代码段中加粗部分的内容进行替换即可。比较常见的Activity窗口显示风格如下。