My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
AndroidActivity  
加入新 Activity
tw, Activity
Updated Sep 4, 2009 by gasolin

直觀來看,每個 Activity 通常會負責處理一個螢幕的內容(包含介面、選單、彈出對話框、程式動作等)。當我們需要從一個螢幕畫面切換到另一個螢幕畫面的時候,就涉及到了 Activity 切換的動作。 我們可以將 Activity 看成 MVC 模式中的 Control。Activity 負責管理 UI(詳細的UI細節可以由資源檔讀入),並接受事件觸發。

以是否需要與其他 Activity 交換資料來區分,Activity 可以粗分為兩種類型:「獨立的 Activity」與「相依的 Activity」。不同類型的 Activity,其動作也不盡相同:

獨立的 Activity

獨立的 Activity 是不需要從其他地方取得資料的 Activity。只是單純的從一個螢幕跳到下個螢幕,不涉及資料的交換。 從一個獨立的 Activity 呼叫另一個獨立的 Activity 時,我們只要填好 Intent 的內容和動作,使用 startActivity 函式呼叫,即可喚起獨立的 Activity。例如前幾章中,用作開啟特定網頁的 Activity。

相依的 Activity

相依的 Activity 是需要與其他 Activity 交換資料的一種 Activity。相依的 Activity 又可再分為單向與雙向。從一個螢幕跳到下個螢幕時,攜帶資料供下一個螢幕(Activity)使用,就是單向相依的 Activity; 要在兩個螢幕之間切換,螢幕上的資料會因另一個螢幕的操作而改變的,就是雙向相依的 Activity。 與獨立的 Activity 比起來,相依的 Activity 變化更加精采。

我們會在後續章節中,對相依的 Activity 做進一步的說明。

獨立的 Activity

本章將繼續透過改進 BMI 應用程式來講解 Android 應用程式設計。在這個過程中,我們將使用到獨立的 Activity。

這章中所做的改動都是為了介紹獨立的 Activity,而不是為了讓 BMI 程式變得更完整。因此你不妨先將寫好的 BMI 程式先壓縮備份到其他目錄中,再隨著後面的教學繼續探索 Android。

本章的目的是介紹獨立的 Activity,會用到兩個螢幕,因此除了原本的一個 XML 描述檔與一個程式碼檔案之外,我們還會額外再定義一個 XML 描述檔與一個程式碼檔案,以支援第二個螢幕的動作。

要完成獨立的 Activity 的動作,我們要做幾件事:

  1. 在程式碼中建立新 Activity 類別檔案
  2. 在清單中新增 Activity 描述
  3. 在原 Activity 類別中加入 startActivity 函式

程式碼中建立新的 Activity 類別檔案

首先,使用 Navigator 檔案瀏覽視窗,切換到「src/com/demo/android/bmi」資料夾。在「bmi」資料夾中,現存有 「Bmi.java」與「R.java」兩個檔案。我們準備在此建立一個新的 Activity 類別檔案。

在「bmi」資料夾圖示上按右鍵,選擇「New->Class」選項。 Eclipse 會跳出一個「New Java Class」對話框。

在對話框中的「Name」一欄上填入「Report」。「Report」的字頭需大寫,這是 Java 程式語言的默認規則。

在「Superclass」一欄右方,按下「Browse...」,Eclipse 會跳出「Superclass Selection」對話框。在對話框中的「Choose a type」欄位中輸入「activity」,輸入框下方的「Matching items」欄位中,會顯示出所有可能的類別。我們選擇「Activity - android.app - ...」這個選項,點擊右下方的「ok」按鈕,回到上一個對話框。

此時,「Superclass」欄位中將填入「android.app.Activity」訊息。按下對話框右下角的「Finish」鍵,Eclipse 會在「bmi」資料夾中,產生一個對應的「Report.java」檔案。

剛產生(尚未修改過的)的「Report.java」檔案如下:

1  package com.demo.android.bmi;
2
3  import android.app.Activity;
4
5  public class Report extends Activity {
6
7  }

解讀程式流程一章中,我們已講解過 Android 程式碼的基本架構,即 XML 描述檔與程式碼兩個主要組成部分。稍後我們要處理建立新程式碼的相關工作,包含定義對應的 XML 描述檔,與在程式碼中,填入這個 class 的內涵。

相關工作

在「res/layout」中新增一個「report.xml」檔案,並把描述使用者介面 一章中講解過的 xml 檔案複製一份過來:

1  <?xml version="1.0" encoding="utf-8"?>
2  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3  	    android:orientation="vertical"
4      android:layout_width="fill_parent"
5	    android:layout_height="fill_parent"
6	>
7	<TextView
8		android:layout_width="fill_parent"
9		android:layout_height="wrap_content"
10		android:text="Hello World, Bmi"
11 />
12 </LinearLayout>

打開「src/com/demo/android/bmi/Report.java」,把解讀程式流程一章中講解過的預設的程式碼複製進來:

1   package com.demo.android.bmi;
2
3   import android.app.Activity;
4   import android.os.Bundle;
5
6   public class Report extends Activity {
7	 /** Called when the activity is first created. */
8	 @Override
9	 public void onCreate(Bundle savedInstanceState) {
10		 super.onCreate(savedInstanceState);
11		 setContentView(R.layout.report);
12	 }
13 }

上面的程式碼中,我們將

setContentView(R.layout.main);

換成了:

setContentView(R.layout.report);

以對應我們新定義的 XML 描述檔產生的資源識別符號。

清單中新增 Activity 描述

我們再打開「AndroidManifest.xml」檔案,並切換到「Application」分頁。在「Application」分頁的左下角,我們可以看到「Application Nodes」欄位中,列出目前已在「AndroidManifest.xml」檔案中定義的所有「Activity」。現在我們就來將 「Report」這個新的 Activity 加入到「AndroidManifest.xml」檔案中。

點擊「Application Nodes」欄位右側的「Add...」按鈕,彈出一個小對話框。 選擇「Activity」後,按下「ok」回到「Application」分頁。「Application Nodes」欄位中會增加一個「Activity」項目。選擇這個「Activity」項目後,在「Application Nodes」欄位右方會出現新的「Attributes for Activity」相關欄位。

我們點選 「Name*」欄位右側的 「Browse...」按鈕,開啟另一個對話框。新的對話框中我們可以選擇在程式中現有定義的 Activity。我們選擇「Report - com.demo.android.bmi」後,按 「ok」 鍵回到「Application」分頁。此時「Name*」欄位的內容變成了「Report」,「Application Nodes」欄位中的名稱也更新成「Report(Activity)」了。

activity 標籤的內容

我們從「Application」分頁切換到「AndroidManifest.xml」分頁,查看剛剛的動作實際上作了些什麼事。

我們發現,在原本的 activity 敘述下方,新增了一行名為「Report」的 activity 標籤,完整的「AndroidManifest.xml」清單內容如下:

1  <?xml version="1.0" encoding="utf-8"?>
2  <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3      package="com.demo.android.bmi">
4     <application android:icon="@drawable/icon">
5         <activity android:name=".bmi" android:label="@string/app_name">
6            <intent-filter>
7               <action android:name="android.intent.action.MAIN" />
8                <category android:name="android.intent.category.LAUNCHER" />
9            </intent-filter>
10        </activity>
11      <activity android:name="Report"></activity>
12   </application>
13 </manifest>

手動新增 activity 標籤

Android 提供了多種方式來協助我們定義「AndroidManifest.xml」清單檔案,除了使用對話框選擇的方式之外,你也可以在原本的「AndroidManifest.xml」檔案中直接修改原始碼,加入如下敘述:

<activity android:name="Report"></activity>

來得到相同的效果。

修改頁面標題文字

如果希望在打開 Report Activity 頁面時,標題欄上的文字將會是「BMI 報告」,而不是預設跟 Activity 名稱相同的「Report」,我們可以在清單裡的「report activity」標籤中,加入標籤(label)屬性的描述。步驟如下。

1. 在「res/values/」目錄下,新建一個 report.xml 描述檔,存放 Report 活動頁面用到的字串。檔案內容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="report_title">BMI 報告</string>
</resources>

2. 有了描述檔後,我們可以再修改「AndroidManifest.xml」清單,為 Report activity 添加標籤(label)屬性:

<activity android:name="Report" android:label="@string/report_title"></activity>

原 Activity 類別中加入 startActivity 函式

在準備好相關資源、並在「AndroidManifest.xml」清單添加新 activity 描述後,我們來到實際控制整個程式流程的程式碼部份。

在程式碼中,我們要把原本按下按鈕即開始計算,並顯示 Bmi 值到同一螢幕的按鈕動作,改成按下按鈕後跳轉到 「Report」 這個 Activity。

首先修改「BMI」這個 Activity。打開「src/com/demo/android/bmi/Bmi.java」檔案,修改「OnClickListener」函式(定義按下按鈕時做的動作)的內容。按下按鈕後從 Bmi Activity 切換(跳轉)到 Report Activity 的程式片段如下:

1   private Button.OnClickListener calcBMI = new Button.OnClickListener()
2   {
3      public void onClick(View v)
4      {
5          //Switch to report page
6          Intent intent = new Intent();
7          intent.setClass(Bmi.this, Report.class);
8          startActivity(intent);
9       }
10 };

修改好後,開啟 Android 模擬器。當我們按下「計算 BMi 值」按鈕後,螢幕會切換到「Hello World, Bmi」頁面(已經進入了 Report Activity)。在這個頁面上,我們並沒有辦法可以直接回到前一個頁面,因為這兩個頁面都是獨立的 Activity。但我們還是可以透過按下硬體的「Undo」鍵,使螢幕切換回原本輸入身高體重的頁面 (即回到 Bmi Activity)。

講解

Intent intent = new Intent();

我們建立一個新的「意圖」(Intent) 實體。

intent.setClass(Bmi.this, Report.class);

為這個意圖指定來源的 Activity 所在 class,與要前往的 Activity 所在的 class。

startActivity(intent);

將定義好的 intent 傳入「startActivity」函式中。「startActivity」函式會將 intent 傳入 Android 框架,Android 框架會根據各應用程式在系統中註冊的資料(有沒有聯想到我們剛剛為 Report Activity 增加的 activity 清單描述?),找出 Report 這個 Activity,並呼叫它。

搞懂之後,原來呼叫一個獨立的 Activity,所需的功夫其實很單純呀。

< 定義 Android 清單 | 回目錄 | 傳送資料到新 Activity >


對於本章,您還期望知道什麼樣的內容呢?請在下方提出建議!

Comment by angela....@Qisda.com, Dec 1, 2008

請問一下如果是繼承ActivityInstrumentationTestCase?的class, 可以用Intent去呼叫一個獨立的Activity嗎? 我用會有問題耶~

Comment by gsmallwi...@gmail.com, Dec 4, 2008

寫的好詳細,對我這樣初學者而言, 幫了很大的忙,希望能繼續寫下去, 感激不盡^^

Comment by b9507...@gmail.com, Jan 20, 2009

Report.java的內容,如果按照所寫的貼上(icicle),所有一個奇怪的error狀況發生(補上;完成描述) 但如果照之前Bmi.java的貼(savedInstanceState),就不會有問題...很怪。

Comment by project member gasolin, Jan 20, 2009

b9507...: Good catch! 這是因為 1.0 後把所有 'icicle' 都改成比較明確的 'savedInstanceState' 參數,而我在更新時線上版沒有更新乾淨 :p

Comment by zcgtai...@gmail.com, May 14, 2009

感激不盡

Comment by ownlyk...@gmail.com, Jul 24, 2009

一開始,我的layout\Report.xml的R是大寫的,好像有問題,後來我給它改成小寫的report.xml,卻整個檔案裡面的程式都出現黃色的底線,但是還是可以run,可是他卻出現這個(skipping index file 'D:\Android_workspace\BMI\res\drawable\Thumbs.db'),請問這是什麼問題呢???

Comment by qazwsxed...@gmail.com, Sep 16, 2009

我出現了當按下Button時會出現"The application BMI(process com.demo.android.bmi)has stopped unexpectedly, Please try again."的錯誤訊息,但debug時並沒有錯誤, 後來發現了是在執行startActivity(intent)時出現錯誤訊息請問我是在設定或者哪些地方寫錯了嗎?除了書本中的R.java與Bmi.java兩個檔在Navigator中不在同一個資料夾裡面,我把 Report.java放在src資料夾下,其他的步驟我都是相同的 可以幫忙解惑嗎? 因為不知道哪裡錯了所以很困擾~謝謝

Comment by project member gasolin, Sep 16, 2009

R.java 是自動產生可以不管它, Bmi.java 跟 Report.java 都要在 src 中呀...可有先參考原始碼? 在 DVD 或http://code.google.com/p/androidbmi/source/browse/trunk/2nd/BMI/src/com/demo/android/bmi/Bmi.java

Comment by uart.ch...@gmail.com, Sep 20, 2009

R.java 我發現是放在 \gen\com\demo\android\bmi 之下耶, 不是src 不過我用的是win32 1.6版的SDK, 不知是否有不一樣的地方.

Comment by project member gasolin, Sep 20, 2009

SDK 1.5 以上 R.java 改放到 gen 目錄下了

Comment by ku392...@gmail.com, Oct 24, 2009

layout的xml檔不准許大寫檔名...害我弄很久

Comment by littlegl...@gmail.com, Jan 4, 2010

很好的入门资料,谢谢

Comment by snakeni...@gmail.com, Jan 7, 2010

在新加入一个activity(假设叫做abc.java),并在res/layout中新增一个xml文件(假设叫做abc.xml),那么src中就会有2个java,res/layout中也会有2个xml,那么我的问题就在,程序是怎样将这2个java文件和2个xml文件对上号的呢?以此类推,如果有n个activity,要配置它们的显示界面,则需要n个xml,那么这n个activity和n个xml是怎样对上号的呢?

Comment by project member gasolin, Jan 7, 2010

AndroidLogic 一章有講到,用 setContentView

Comment by snakeni...@gmail.com, Jan 7, 2010

问题解决了,我自己犯糊涂了XD,谢谢~

Comment by project member gasolin, Jan 7, 2010

看來應該多補一些關係圖,這樣才會更清晰 @@

Comment by JHS.John...@gmail.com, Feb 1, 2010

学完这一章,收获颇多,期待「相依的 Activity」的例子; 再次感谢如此详细的描述!!

Comment by project member gasolin, Feb 1, 2010

JHS.Johnson, 可以直接找「Google Android开发入门指南」實體書來看

Comment by owen.cs9...@gtempaccount.com, Apr 16, 2010

我也出現"The application BMI(process com.demo.android.bmi)has stopped unexpectedly, Please try again."可能是哪裡出錯了呢?

Comment by divin...@gmail.com, Jun 21, 2010

我出現了以下的訊息G:\Documents and Settings\user\workspace\BMI\res\layout\report.xml:1: error: Error parsing XML: no element found 是表示我的report.xml有東西沒有建立起來嗎?

Comment by puremonk...@gmail.com, Sep 30, 2010

Thanks for your clear tutorial. It does help me know Android more.

Comment by xpecial...@gmail.com, Jan 5, 2011

thank you for your kind tutorial.

Comment by skyso...@gmail.com, Jan 28, 2011

若是出現 Unparsed aapt error ....等錯誤 或是console 底下無任何錯誤訊息 請執行Project->clean動作 再試一次

Comment by pauleagl...@gmail.com, Feb 8, 2011

intent.setClass(Bmi.this, Report.class); 這個怪怪的

我覺得應該寫 intent.setClass(this, Report.class); 比較合理

Comment by pauleagl...@gmail.com, Feb 8, 2011

我看出為什麼了...在private inner class 的method裡面的關係

參考資料 : http://www.jguru.com/faq/view.jsp?EID=13498

Comment by project member gasolin, Feb 8, 2011
pauleagl..., 謝謝補充啦 :)
Comment by k650...@gmail.com, Feb 18, 2011

gasolin大大, 您好:

想請教一下, 在 /res/values/ 內可以自訂多個xml檔來記錄一些文字, 例如前面有提到的 /res/values/strings.xml /res/values/advice.xml /res/values/report.xml Android會自動根據 /res/ 內的檔案變化自動去修改 R.java 的內容,

我的第一個疑問是, 根據我觀察 R.java 的內容後, 我發現 public static final class string {...} 區塊內的那一堆"變數名"就是直接取用上述那些 xml 內的<string name="變數名">值</string> 這是否就代表一件我們本身要注意的事, 就是上述各個 xml 內的 <string name="變數名">值</string> 這個變數名即使是在不同xml檔之間也不能夠重覆, 例如: strings.xml 內有個 <string name="ok_label">確認</string> advice.xml 內也有個 <string name="ok_label">確認</string> 這樣是不可以的, 對嗎?

第二個疑問是, 上述這些 xml 的檔名, 除了要注意用小寫字母之外, 檔名本身似乎並不跟自動更新 R.java 的過程產生關連? 我的猜想認知是, 在自動更新 R.java 的過程中, 它只管去找出 /res/values/ 內所有的 xml 檔, 然後把所有的 <string name="變數名">值</string> 整合起來, xml 檔名本身一點都不重要, 例如我突然發神經, 把 advice.xml 改成 foobar.xml 並不會有任何影響, 是這樣嗎?

Comment by project member gasolin, Feb 18, 2011
k650...., 1. 是的. 但照multiple layout規則時, 不同目錄下xml檔裡可以有多個重複的變數名來表示各語系的字串, 系統會自動選擇

2. xml檔名只是方便辨認而已

Comment by k650...@gmail.com, Feb 20, 2011

謝謝您, 我已經決定買您的書了, 超棒!!

Comment by attack78...@gmail.com, May 25, 2011

請問有辦法可以在同一個頁面 按下不同Button切換到多個activity和返回嗎? 語法大概要怎麼寫 測了好多次都不行 希望可以得到解答XD

Comment by project member gasolin, May 25, 2011

attack78...., 去抓ADK裡面Sample目錄中的API Demos,就有一堆範例了

Comment by s9772...@gm.pu.edu.tw, Oct 21, 2011

請問!!要如何更換activity的出場順序

假設現在是 A1→A2 如何改成 A2→A1


Sign in to add a comment
Powered by Google Project Hosting