本篇隨筆將會深入學習Activity,包括如何定義多個Activity,並設定為預設的Activity、如何從一個Activity跳轉到另一個Activity,還有就是詳細分析Activity的生命週期函式。
一、如何定義多個Activity
在我們之前寫的程式當中,我們都是用的MainActivity這個由ADT自動生成的Activity,但是我們一個程式可能有多個Activity,那麼我們應該如何定義多個Activity呢?步驟如下:
1.定義一個類讓其繼承Activity這個父類
2.重寫父類的onCreate()方法
3.在AndroidManifest.xml檔案中註冊這個Activity
首先我們再寫一個佈局檔案second.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/firstTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="FirstActivity" /> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_below="@id/firstTextView" android:text="SecondActivity"/> </RelativeLayout>
接著寫一個類SecondActivity,繼承Activity這個類,並重寫onCreate()方法
package com.xiaoluo.android_multiactivity; import android.app.Activity; import android.os.Bundle; public class SecondActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second); } }
最後在我們的AndroidManifest.xml檔案中對這個Activity進行註冊
<activity android:name="com.xiaoluo.android_multiactivity.SecondActivity" android:label="SecondActivity">
<!--如果加上了下面這個子元素,則表示該Activity是這個應用程式預設啟動的Activity--> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
這樣,我們在啟動了我們的應用程式後,就會預設載入SeoncdActivity,然後載入我們的佈局檔案
二、如何從一個Activity跳轉到另一個Activity
我們在知道如何定義多個Activity後,接下來要了解的就是如何從一個Activity跳轉到另一個Activity上,就像我們web程式一樣,首先進入一個主頁,然後再通過按鈕或者連結跳轉到另外的頁面上。我們先來看看兩個佈局檔案
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/firstTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="FirstActivity" /> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:layout_below="@id/firstTextView" android:text="SecondActivity"/> </RelativeLayout>
second.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/secondTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="第二個Activity"/> </LinearLayout>
我們希望通過點選第一個Activity的Button按鈕跳轉到第二個Activity上
我們來看看MainActivity這個類該怎樣寫:
package com.xiaoluo.android_multiactivity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button)findViewById(R.id.button); ButtonListener buttonListener = new ButtonListener(); button.setOnClickListener(buttonListener); } class ButtonListener implements OnClickListener { @Override public void onClick(View v) { // 在android中,要做各種事,例如啟動一個Activity,都需要生成一個Intent(意圖)物件 Intent intent = new Intent(); /* * Context是一個類,所有的Activity都是Context的一個子類,所以 * setClass方法的第一個引數接收的是一個Context型別物件,我們將當前這個Activity物件傳進去就可 * 第二個引數就是我們需要啟動的Activity的class物件 */ intent.setClass(MainActivity.this, SecondActivity.class); startActivity(intent); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
啟動另一個Activity最重要的方法就是首先建立一個Intent物件,在Android中,我們幾乎要做的任何事,都是要通過Intent(意圖)物件來做的,然後通過setClass方法來設定我們要跳轉的Activity的類,最後呼叫startActivity方法來跳轉到我們的Activity上。
這樣當我們點選了第一個Activity的Button按鈕後,就會跳轉到第二個Activity上。
三、Back Stack
這一節我們來稍微探討一下Android當中的Back Stack這個東西,back stack可稱為後退棧,裡面存放的是我們的Activity物件,我們知道棧是一種後進先出的資料結構,當我們的應用程式啟動時,Android會自動建立我們預設的一個Activity物件,將其放在棧底,當我們從這個Activity跳轉到另一個Activity物件上時,此時就會生成第二個Activity的一個物件,然後將其放在back stack中,這樣第二個Activity物件就位於棧頂了,要記住:Android應用程式顯示的永遠都是棧頂的Activity。當來第三個Activity物件時,同樣將其放入back stack當中,此時第三個Activity就成為了棧頂物件,這樣我們看到的就是第三個Activity物件對應的佈局檔案,如果此時我們點選返回按鈕,此時根據棧的"後進先出"原則,首先將棧頂的第三個Activity物件從back stack中彈出去,這時位於棧頂的就是第二個Activity物件,此時介面就是這個Activity物件的佈局檔案,再點選返回,又將第二個Activity物件彈出去,此時就會顯示第一個Activity物件的佈局檔案,這就是為什麼我們點選返回後會跳到上層頁面的原因所在!
四、Activity的生命週期
最後一節,將來詳細探討一下Activity的生命週期,我們要了解在Activity物件從建立到最後被銷燬中間經歷了哪些階段,每個階段我們又能讓其為我們做什麼?
Activity的生命週期分為7段,每個階段都有一個對應的生命週期函式,我們首先來看一張圖,來看看這七個生命週期函式所執行的時間
我們下面來通過一個例子來詳細的探討這7個生命週期函式呼叫的時機,同樣是從一個Activity調到另一個Activity,然後我們在每個函式裡列印出對應的資訊,來看看生命週期函式呼叫的時機:
首先來看看兩個佈局檔案,很簡單
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <Button android:id="@+id/button" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/textView1" android:text="跳轉到SecondActivity"/> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="SecondActivity"/> </LinearLayout>
接著來看看我們的兩個Activity類:
MainActivity:
public class MainActivity extends Activity { private Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button)findViewById(R.id.button); ButtonListener buttonListener = new ButtonListener(); button.setOnClickListener(buttonListener); System.out.println("MainActivity: onCreate"); } class ButtonListener implements OnClickListener { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setClass(MainActivity.this, SecondActivity.class); startActivity(intent); } } @Override protected void onStart() { super.onStart(); System.out.println("MainActivity: onStart"); } @Override protected void onResume() { super.onResume(); System.out.println("MainActivity: onResume"); } @Override protected void onPause() { super.onPause(); System.out.println("MainActivity: onPause"); } @Override protected void onStop() { super.onStop(); System.out.println("MainActivity: onStop"); } @Override protected void onRestart() { super.onRestart(); System.out.println("MainActivity: onRestart"); } @Override protected void onDestroy() { super.onDestroy(); System.out.println("MainActivity: onDestroy"); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
SecondActivity類:
public class SecondActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.second); System.out.println("SecondActivity: onCreate"); } @Override protected void onStart() { super.onStart(); System.out.println("SecondActivity: onStart"); } @Override protected void onResume() { super.onResume(); System.out.println("SecondActivity: onResume"); } @Override protected void onPause() { super.onPause(); System.out.println("SecondActivity: onPause"); } @Override protected void onStop() { super.onStop(); System.out.println("SecondActivity: onStop"); } @Override protected void onRestart() { super.onRestart(); System.out.println("SecondActivity: onRestart"); } @Override protected void onDestroy() { super.onDestroy(); System.out.println("SecondActivity: onDestroy"); } }
最後,要記住,在AndroidManifest.xml檔案中對Activity進行註冊,並設定一個預設啟動的Activity,我們這裡就是MainActivity:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xiaoluo.android_lifecycle" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.xiaoluo.android_lifecycle.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.xiaoluo.android_lifecycle.SecondActivity" android:label="SecondActivity"> </activity> </application> </manifest>
下面我們啟動我們的程式,然後點選第一個Activity的Button按鈕跳轉到第二個Activity上,再點選返回按鈕返回到第一個Activity上,我們來看看控制檯的輸出,並解析其為什麼會列印出這樣的語句,也就是為什麼會在這個時候呼叫該周期函式:
首先會列印出這三條語句,因為我們預設啟動的是MainActivity物件,所以此時當Activity物件一啟動並顯示出能與使用者互動的介面時會分別呼叫 onCreate、onStart和onResume方法,此時我們點選Button按鈕跳轉到第二個Activity上:
此時,根據上面我們的那張表格知道,當一個Activity準備跳轉到另一個Activity上時,當前這個Activity物件會呼叫onPause方法,此時跳轉到第二個Activity上時,會因此呼叫第二個Activity物件的onCreate、onStart和onResume方法,最後,因為第二個Activity的介面完全覆蓋了第一個Activity,所以此時會呼叫第一個Activity物件的 onStop 方法
這時我們點選返回來回到第一個Activity頁面上:
我們看到,因為此時也是從一個Activity跳轉到另一個Activity,所以此時會呼叫第二個Activity物件的onPause方法,那麼為什麼此時會接著呼叫我們第一個Activity物件的onRestart方法呢?這時就要回顧下我們第三節的那個 back stack 知識點了,我們知道,當建立一個Activity物件後,會將其因此放入back stack棧中,Android顯示的總是棧頂的Activity物件,因為當前預設啟動的是MainActivity物件,所以MainActivity物件是放在最下面,SecondActivity物件放在棧頂上,當我們點選返回時,會將SecondActivity物件從棧中彈出去,所以此時因為MainActivity物件是存在於stack棧中的,所以此時會呼叫其 onRestart 方法,而不是onCreate方法,緊接著就是呼叫 onStart、onResume方法,最後第一個Activity覆蓋了第二個Activity,所以分別又會呼叫SecondActivity物件的 onStop和 onDestroy方法,將SecondActivity物件銷燬。
這就是我們整個的Activity物件的生命週期函式的呼叫含義,我們來看看Android官方提供的Activity生命週期圖:
相信結合上述例子以及android官方提供的Activity生命週期圖,大家應該會對Activity物件的生命週期瞭如指掌了吧。
五、Activity物件的三種狀態
最後我們再來了解一個知識點--Activity物件的三種狀態:
①Resumed狀態:此時我們的Activity處於活動狀態,可以與使用者進行互動。
②Paused狀態:此時我們啟動了第二個Activity,但是第一個Activity物件並沒有消失掉,例如彈出式的對話方塊,此時就屬於Paused狀態。
③Stopped狀態:此時第二個Activity完全覆蓋了第一個Activity,這時第一個Activity物件就處於Stopped狀態。
總結:本篇隨筆講解了如何定義多個Activity,並學習瞭如何從一個Activity跳轉到另外的Activity上,最後還詳細講解了Activity的生命週期,我們在瞭解了Activity的生命週期函式呼叫時機後,就可以靈活的在對應的方法中來完成我們需要完成的功能了。