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