3.2 Activity

Activity是Android组件中最基本也是最为常见的组件。Activity是用户接口程序,原则上它会提供给用户一个交互式的接口功能,几乎所有的Activity都要和用户打交道,也有人把它比喻成Android的管理员。需要在屏幕上显示什么、用户在屏幕上做什么、处理用户的不同操作等都由Activity来管理和调度。

Activity提供用户与Android系统交互的接口,用户通过Activity来完成自己的目的,例如打电话、拍照、发送E-mail、查看地图等。每个Activity都提供一个用户界面窗口,一般情况下,该界面窗口会填满整个屏幕,但是也可以比屏幕小,或者浮在其他的窗口之上。

一个Android应用程序通常由多个Activity组成,但是其中只有一个为主Activity,其作用相当于Java应用程序中的main函数,当应用程序启动时,作为应用程序的入口首先呈现给用户。Android应用程序中的多个Activity可以直接相互调用以完成不同工作。当新的Activity被启动的时候,之前的Activity会停止,但是不会被销毁,而是被压入“后退栈(Back Stack)”的栈顶,新启动的Activity获得焦点,显示给用户。“后退栈”遵循“后入先出”的原则。当新启动的Activity被使用完毕,用户单击“Back”按钮时,当前的Activity会被销毁,而原先的Activity会被从“后退栈”的栈顶弹出并且激活。

当Activity状态发生改变时,都会通过状态回调函数通知Android系统。而程序编写人员可以通过这些回调函数对Activity进行进一步的控制。

下面对Activity生命周期及其涉及的回调函数进行简单介绍。

3.2.1 Activity的生命周期

从本质上讲,Activity在生命周期中共存在三个状态,分别如下。

• 运行态:运行态指Activity运行于屏幕的最上层并且获得了用户焦点。

• 暂停态:暂停态是指当前Activity依然存在,但是没有获得用户焦点。在其之上有其他的Activity处于运行态,但是由于处于运行态的Activity没有遮挡住整个屏幕,当前Activity有一部分视图可以被用户看见。处于暂停态的Activity保留了自己所使用的内存和用户信息,但是在系统极度缺乏资源的情况下,有可能会被杀死以释放资源。

• 停止态:停止态是指当前Activity完全被处于运行态的Activity遮挡住,其用户界面完全不能被用户看见。处于停止态的Activity依然存活,也保留了自己所使用的内存和用户信息,但是一旦系统缺乏资源,停止态的Activity就会被杀死以释放资源。

Activity在生命周期中从一种状态到另一种状态时会激发相应的回调方法,这些回调方法包括:

• onCreate(Bundle savedInstanceState)。创建Activity时调用。设置在该方法中,还以Bundle的形式提供对以前储存的任何状态的访问。其中参数savedInstanceState对象是用于保存Activity的对象的状态。

• onStart()。Activity变为在屏幕上对用户可见时调用。

• onResume()。Activity开始与用户交互时调用(无论是启动还是重启一个活动,该方法总是被调用)。

• onPause()。当Android系统要激活其他Activity时,该方法被调用,暂停或收回CPU和其他资源时调用。

• onStop()。Activity被停止并转为不可见阶段时调用。

• onRestart()。重新启动已经停止的Activity时调用。

• onDestroy()。Activity被完全从系统内存中移除时调用,该方法被调用可能是因为有人直接调用finish()方法或者系统决定停止该活动以释放资源。

上面7个生命周期方法分别在4个阶段按着一定的顺序进行调用,这4个阶段如下:

• 启动Activity。在这个阶段依次执行3个生命周期方法:onCreate、onStart和onResume。

• Activity失去焦点。如果在Activity获得焦点的情况下进入其他的Activity或应用程序,这时当前的Activity会失去焦点。在这一阶段,会依次执行onPause和onStop方法。

• Activity重获焦点。如果Activity重新获得焦点,会依次执行3个生命周期方法:onRestart、onStart和onResume。

• 关闭Activity。当Activity被关闭时,系统会依次执行3个生命周期方法:onPause、onStop和onDestroy。

Activity生命周期中方法的调用过程如图3.1所示。

图3.1 Activity生命周期

通过图3.1,可以很直观地了解到Activity的整个生命周期。Activity的生命周期表现在三个层面,如图3.2所示。

图3.2 Activity的整个生命周期

通过图3.2可以更清楚地了解Activity的运行机制。如果Activity离开可见阶段,长时间失去焦点,就很可能被系统销毁以释放资源。当然,即使该Activity被销毁掉,用户对该Activity所做的更改也会被保存在Bundle对象中,当用户需要重新显示该Activity时,Android系统会根据之前保存的用户更改信息将该Activity重建。

3.2.2 Activity的创建

在一个Android工程中,创建Activity的步骤如下:

步骤01 新建类。创建一个Activity,必须创建Android.app.Activity(或者它的一个已经存在的子类)的一个子类,并重写onCreate()方法。

步骤02 关联布局XML文件。在新建的Activity中设置其布局方式,需要在res/layout目录中新建一个XML布局文件,可以通过setContentView()来指定Activity的用户界面的布局文件。

步骤03 注册。在AndroidManifest.xml文件中对建立的Activity进行注册,即在<application>标签下添加<activity>标签。例如,注册ExampleActivity的代码如下:

对于主Activity,要为其添加<intent-filter>标签,代码如下:

其中,<action Android:name="Android.intent.action.MAIN" />表示该Activity作为主Activity出现,而<category Android:name="Android.intent.category.LAUNCHER" />表示该Activity会被显示在最上层的启动列表中。

3.2.3 启动Activity

在Android系统中,除了主Activity由系统启动外,其他Activity都要由应用程序来启动。

(1)通常情况下,通过startActivity()方法来启动Activity,而要启动的Activity的信息由Intent对象来传递,例如:

     Intent intent=new Intent(this, AnotherActivity.class);
     startActivity(intent);

表示通过当前的Activity启动名为AnotherActivity的Activity。

有时,用户不需要知道要启动的Activity的名字,而可以仅制定要完成的行为,由Android系统来为用户挑选合适的Activity,例如:

     Intent intent=new Intent(Intent.ACTION_SEND);
     intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
     startActivity(intent);

其中,Intent.EXTRA_EMAIL放置的是recipientArray中存储的要发送的E-mail的目标地址。该Intent对象被startActivity()启动后,Android系统会启动相应的E-mail处理应用程序,并将Intent.EXTRA_EMAIL中的内容放置到邮件的目标地址中。

(2)有时,当需要从启动的Activity获取返回值的时候,需要使用startActivityForResult()方法代替startActivity()方法,并实现onActivityResult()方法来获取返回值。

例如,在发送短信的时候,用户需要从联系人列表中获取联系人的信息,然后返回到短信发送界面,代码如下:

     Intent intent=new Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI);
     startActivityForResult(intent, PICK_CONTACT_REQUEST);

当用户选择了联系人后,相关信息会被存储到Intent对象中,并返回到onActivityResult()方法中。

3.2.4 关闭Activity

关闭Activity使用finish()方法。关闭之前启动的其他Activity可以使用finishActivity()方法。

需要注意的是,虽然Android SDK提供了关闭Activity的方法,但是通常情况下,程序员不应该使用这些方法去强制关闭Activity。因为Android系统在为用户维护Activity的生命周期,并且提供了完备的资源回收机制和资源重建机制,可以动态地回收和重建Activity,因此Activity应用交由Android系统来管理,除非已确定用户不再需要当前的Activity,并且不允许用户回退到当前Activity。

3.2.5 Activity数据传递

Activity数据传递共有三种:

• 通过Intent传递一些简单的数据。

• 通过Bundle传递相对复杂的数据或者对象。

• 通过startActivityForResult可以更方便地进行来回传递,当然前两种方法也可以来回传递。

假设由Activity1向Activity2传递数据,利用三种方式实现的实例代码如下。

(1)利用Intent传递数据。

在传递数据的Activity1中:

     Intent intent=new Intent(Activity1.this,Activity2.class);
     intent.putExtra("author","leebo");//在Intent 中加入键值对数据,键为“author”,值为“leebo”
     Activity1.this.startActivity(intent);

在取出数据的Activity2中:

     Intent intent=getIntent();//获得传过来的Intent
     String value=intent.getStringExtra("author");
     //根据键名author 取出对应键值为“leebo”

(2)利用Bundle传递数据。

在传递数据的Activity1中:

     Intent intent=new Intent(Activity1.this,Activity2.class);
     Bundle myBundle=new Bundle();
     myBundle.putString("author","leebo");
     intent.putExtras(myBundle);
     Activity1.this.startActivity(intent);

在取出数据的Activity2中:

     Intent intent=getIntent();
     Bundle myBundle=intent.getExtras();
     String value=myBundle.getString("author"); //根据键名author 取出对应键值为“leebo”

(3)利用startActivityForResult()传递数据。

startActivityForResult()方法不但可以把数据从Activity1传递给Activity2,还可以把数据从Activity2传回给Activity1。

在Activity1中:

     final int REQUEST_CODE=1;
     Intent intent=new Intent(Activity1.this,Activity2.class);
     Bundle mybundle=new Bundle();
     mybundle.putString("author", "leebo");//把数据传过去
     intent.putExtras(mybundle);
     startActivityForResult(intent, REQUEST_CODE);

重载onActivityResult方法,用来接收传过来的数据(接收b中传过来的数据):

在Activity2中:

     Intent intent=getIntent();
     Bundle myBundle=getIntent().getExtras();
     String author=getBundle.getString("author");
     Intent intent=new Intent();
     Bundle bundle=new Bundle();
     bundle.putString("Result","from Activity2");
     intent.putExtras(bundle);
     Activity02.this.setResult(RESULT_OK,intent);//通过intent 将数据返回给Activity1,RESULT_ OK
是结果码:
     finish();//结束当前的Activity

本质上,这三种数据传递方式都是通过Intent来完成的。