Activity概述
一个应用当中通常有若干个关系松散的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>的子元素。
java代码:
- <manifest ... >
- <application ... >
- <activity android:name=".ExampleActivity" />
- </application ... >
- </manifest >
这里还可以定义其他一些属性,比如说定义标签,图标或者是UI的样式等。使用intent filters 一个Activity可以具有多个intent filters(具体方式是在配置文件中声明<intent-filter>),这样可以方便其他activity访问。可以理解成一个能力描述符,用来标识自己有哪些处理能力,当其他activity需要处理相应请求时,可以找到这个activity。
当使用Android SDK工具创建一个新的应用时,工具会自动帮我们创建一个filter,它的样式如下:
java代码:
- <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的情况,启动Activity 可以通过调用startActivity()来启动另外一个Activity,只需要传递相应的Intent参数描述被启动项即可。Intent可以描述需要启动的Activity,也可以描述启动时需要的动作,还可以带有少量的数据。当工作在自己的应用当中时,我们经常需要启动某个activity。这时,我们可以在intent当中指定要启动的activity的类名。例如,我们想启动一个类名为SignInActivity的activity,会使用如下代码:
java代码:
- Intent intent = new Intent(this, SignInActivity.class);
- startActivity(intent);
如果我们的应用还想做一些额外动作,比如说发送邮件、发送短信等。但可能我们的应用本身不具备这样的功能,这时我们就要请求系统当中有这种能力的应用来帮我们。做这件事情比较简单,我们只需要创建一个intent,设置我们想要执行的动作,设置需要的数据,然后发送出去即可。这时,如果系统当中有多个应用可以提供这些功能,系统会提示用户去选择一个应用。具体代码如下:
java代码:
- 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()中返回。
例如,我们需要用户去选择一个联系人,然后再对这些联系人做一些操作。下面的代码演示了这个过程:
java代码:
- private void pickContact(){
- 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 (resultCode == Activity.RESULT_OK && requestCode == PICK_CONTACT_REQUEST) {
- Cursor cursor = getContentResolver().query(data.getData(), new String[] {Contacts.DISPLAY_NAME}, null, null, null);
- if (cursor.moveToFirst()) {
- int columnIndex = cursor.getColumnIndex(Contacts.DISPLAY_NAME);
- String name = cursor.getString(columnIndex);
- }
- }
- }
【编辑推荐】