Android 5从入门到精通
上QQ阅读APP看书,第一时间看更新

3.2 Activity

Activity是Andorid组件中最基本也是最为常见的组件。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被销毁掉,用户对该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的代码如下:

    <application ...>
         <activity Android:name=".ExampleActivity" />
          ...
    </application ...>

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

    <activity Android:name=".ExampleActivity" Android:icon="@drawable/app_icon">
       <intent-filter>
           <action Android:name="Android.intent.action.MAIN" />
           <category Android:name="Android.intent.category.LAUNCHER" />
       </intent-filter>
    </activity>

其中<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中传过来的数据):

    protected void onActivityResult(int requestCode, int resultCode,Intent intent){
    if(requestCode==this.REQUEST_CODE){
       switch(resultCode){
       case RESULT_OK:
          Bundle b=intent.getExtras();
          String str=b.getString("Result"); //获取到Result中的值,为“from Activity2”
           break;
      default:
            break;
      }
      }
    }

在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来完成的。