Activity概述
Activity是一个应用中的组件,它为用户提供一个可视的界面,方便用户操作,比如说拔打电话、照相、发邮件或者是浏览地图等。每个activity会提供一个可视的窗口,一般情况下这个窗口会覆盖整个屏幕,但在某此情况下也会出现一些比屏幕小的窗口飘浮在另外一相窗口上面。类比Windows当中的概念,Activity相应于一个Dialog(MFC)或者是Form(C#),它为用户提供一个可视的界面。
一个应用当中通常有若干个关系松散的activities组成。通常情况下,一个应该中有一个activity是主activity,它会在应用程序加载时展现出来,之后每个activity都有机会启动其他activity,从而产生不同的动作。每当一个新的activity启动的时候,它的前一任就会停下来,这时系统将前任放在一个栈(后台栈)中。这个后台栈遵循先进后出原则,所以当用户对当前activity完成操作并按后退键时,原来栈中的activity就会从栈中弹出,恢复执行。(我们会在任务和后台栈中详细讨论后台栈)
新activity启动,旧activity停止,这些操作会通过调用activity的生命周期回调函数来进行通知。对于activity来说,它可能会收到很多回调,这些回调会在系统创建、停止、恢复或者销毁一个activity时调用,这样,activity就有机会感知变化进行在相应的回调中做出正确的处理。例如,当activity停止时,它应该释放掉所有的大型对象,比如说网络连接或数据库连接。当activity恢复执行时,可以重新获取需要的资源并从中断处重新运行。这些状态的变化就是一个activity的生命周期。
创建一个Activity
创建一个Activity,必须要继承Activity或者是继承它相应的子类。在我们的子类当中,还需要实际一系列与生命周期转化密切相关的接口函数,比如说创建、停止、恢复或销毁等回调接口。最重要的两个回调函数是:
onCreate()
必须要实现的方法。当我们的Activity创建的时候,系统会调用此方法。在我们实现当中,需要初始化activity当中重要的组件。需要强调的是,在这个方法里,需要调用setContentView()来为activity的用户界面调用布局。
onPause()
当用户离开activity的时候,系统会调用这个函数。用户可能不再会回来调用此activity,因此需要在本方法中把需要永久存储的数据进行提交。
除了这两个方法之外,在activity整个生命周期中还有很多回调方法需要关注。在后面我们会讨论其他回调方法的作用。
创建一个用户界面
Activity的用户界面是由View来控制的。每个view控制着一片矩形区域并会对用户的操作进行反馈。例如,一个view可能是一个按钮,当用户按下时,它会触发一个事件。
Android系统提供了不少内置的view,我们可以用它们来设计我们的布局。"Wedgets"是一类可以显示的views,比如说button,textfiled,checkbox或者image。"Layouts"是从ViewGroup继承出来的类,它可以提供一种固定的布局模式,比如说linear layout,grid layout,或者relative layout。我们当然还可以继承View和ViewGroup来实现自己的控件和布局。
使用views最常见的方式是在资源文件中的XML中定义它。这种方式可以使设计和行为的源代码分开。我们可以通过调用setContentView()来为Activity设置布局。不过,我们也可以在代码中添加Views,首先往ViewGroup中插入相应的Views,再将ViewGroup的根元素传递给setContentView()即可。
在manifest中声明activity
必须在manifest文件中声明activity,不然系统可以无法访问我们的activity。步骤是,打开manifest文件,为<application>元素添加一个叫<activity>的子元素。
<
manifest
...
>
<
application
...
>
<
activity
android:name
=".ExampleActivity"
/>
...
</
application ...
>
...
</
manifest
>
这里还可以定义其他一些属性,比如说定义标签,图标或者是UI的样式等。
使用intent filters
一个Activity可以具有多个intent filters(具体方式是在配置文件中声明<intent-filter>),这样可以方便其他activity访问。可以理解成一个能力描述符,用来标识自己有哪些处理能力,当其他activity需要处理相应请求时,可以找到这个activity。
当使用Android SDK工具创建一个新的应用时,工具会自动帮我们创建一个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>元素说明这是应用程序的"main"入口。<category>元素表示该activity会被记录在系统的启动器当中(允许用户启动这个activity)。
如果我们不想让自己的应用被其他应用访问的话,就无需再多声明fileters了。在一个应用当中只有一个activity的filter可以有main action和launcher category。对于没有声明filters的activities,可以通过在intent中明确指出要调用的activity的类来启动它。
如果我们想让我们的activity接收其他activity的访问并返回给对方结果的话,我们必须额外地再添加filters。对于我们想要回复的filters,我们必须在<intnent-filter>下面添加<action>元素,也可以选择性地包含<category>元素和<data>元素。
欲知更多关于intents的情况,可以参考Intents 和Intent Filters章节。(还没写,不知有没有信心写到那里)
启动Activity
可以通过调用startActivity()来启动另外一个Activity,只需要传递相应的Intent参数描述被启动项即可。Intent可以描述需要启动的Activity,也可以描述启动时需要的动作,还可以带有少量的数据。
当工作在自己的应用当中时,我们经常需要启动某个activity。这时,我们可以在intent当中指定要启动的activity的类名。例如,我们想启动一个类名为SignInActivity的activity,会使用如下代码:
Intent intent
=
new
Intent(
this
, SignInActivity.
class
);
startActivity(intent);
如果我们的应用还想做一些额外动作,比如说发送邮件、发送短信等。但可能我们的应用本身不具备这样的功能,这时我们就要请求系统当中有这种能力的应用来帮我们。做这件事情比较简单,我们只需要创建一个intent,设置我们想要执行的动作,设置需要的数据,然后发送出去即可。这时,如果系统当中有多个应用可以提供这些功能,系统会提示用户去选择一个应用。具体代码如下:
Intent intent
=
new
Intent(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_EMAIL, recipientArray);
startActivity(intent);
为EXTRA_EMAIL添加的数据是一个字符串数组,其中包含邮件列表。当邮件应用回应这个intent时,它会读取数组中的地址,然后设置邮件格式,发送邮件。
以需要返回结果的方式启动Activity
有时,我们可能需要从我们启动的activity当中获取结果。这时,我们在启动activity时就要调用startActivityForResult()方法。然后,我们在哪接收返回的数据呢?按照android的习惯,此时我们需要实现一个回调接口onActivityResult()。当我们启动的activity完成时,它会以intent的形式在onActivityResult()中返回。
例如,我们需要用户去选择一个联系人,然后再对这些联系人做一些操作。下面的代码演示了这个过程:
private
void
pickContact(){
//
Create an intent to "pick" a contact, as defined by the content
provider URI Intent intent
=
new
Intent(Intent.ACTION_PICK, Contacts.CONTENT_URI); startActivityForResult(intent, PICK_CONTACT_REQUEST);}@Override
protected
void
onActivityResult(
int
requestCode,
int
resultCode, Intent data) {
//
If the request went well (OK) and the request was PICK_CONTACT_REQUEST
if
(resultCode
==
Activity.RESULT_OK
&&
requestCode
==
PICK_CONTACT_REQUEST) {
//
Perform a query to the contact's content provider for the contact's name
Cursor cursor
=
getContentResolver().query(data.getData(),
new
String[] {Contacts.DISPLAY_NAME},
null
,
null
,
null
);
if
(cursor.moveToFirst()) {
//
True if the cursor is not empty
int
columnIndex
=
cursor.getColumnIndex(Contacts.DISPLAY_NAME); String name
=
cursor.getString(columnIndex);
//
Do something with the selected contact's name...
} }}
上面的代码显示了如何在onActivityResult()中获取数据的基本逻辑。第一步是检查请求是否成功,如果成功的话resultCode会是RESULT_OK。第二个参数,再检查请求是否为正常的请求(当有多个请求时,可能会返回多个intent,你只要处理你关心的请求回复即可)。第三个参数,就是返回的Intent,可以从中获取数据。
后面的ContentResolver获取了一个content provider,它返回一个Cursor,使用这个Cursor可以读取到数据。具体的使用我们会在Content Provider中讲述(再挖一坑,不知何年何月才能写到那)
关闭Activity
可以通过finish()方法来关闭一个Activity,也可以通过调用finishActivity()关闭一个由自己启动的Activity。
注意:一般我们不自己去关闭Activity,而是交由系统去管理Activity的生命周期。Activity生命周期是非常重要部分,我们将在下节讨论。