Android 元件系列-----Activity生命週期

xiaoluo501395377發表於2013-10-31

本篇隨筆將會深入學習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的生命週期函式呼叫時機後,就可以靈活的在對應的方法中來完成我們需要完成的功能了。

 

相關文章