Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Activity詳解

Android Activity詳解

編輯:關於Android編程

Activity 的生命周期

和 J2ME 的 MIDlet 一樣,在android 中,Activity的生命周期交給系統統一管理。與 MIDlet不同的是安裝在 android中的所有的 Activity都是平等的。

Activity 的狀態及狀態間的轉換

在 android中,Activity 擁有四種基本狀態:

1.Active/Runing一個新 Activity啟動入棧後,它在屏幕最前端,處於棧的最頂端,此時它處於可見並可和用戶交互的激活狀態。

2.Paused當 Activity被另一個透明或者 Dialog樣式的 Activity覆蓋時的狀態。此時它依然與窗口管理器保持連接,系統繼續維護其內部狀態,所以它仍然可見,但它已經失去了焦點故不可與用戶交互。

3.Stoped當 Activity被另外一個 Activity覆蓋、失去焦點並不可見時處於Stoped狀態。

4.KilledActivity被系統殺死回收或者沒有被啟動時處於Killed狀態。

當一個 Activity實例被創建、銷毀或者啟動另外一個 Activity時,它在這四種狀態之間進行轉換,這種轉換的發生依賴於用戶程序的動作。下圖說明了 Activity 在不同狀態間轉換的時機和條件:

Android 程序員可以決定一個Activity 的“生”,但不能決定它的“死”,也就時說程序員可以啟動一個Activity,但是卻不能手動的“結束”一個Activity。當你調用Activity.finish()方法時,結果和用戶按下BACK 鍵一樣:告訴Activity Manager 該Activity 實例完成了相應的工作,可以被“回收”。隨後Activity Manager 激活處於棧第二層的Activity 並重新入棧,同時原Activity 被壓入到棧的第二層,從Active 狀態轉到Paused 狀態。例如:從Activity1 中啟動了Activity2,則當前處於棧頂端的是Activity2,第二層是Activity1,當我們調用Activity2.finish()方法時,Activity Manager重新激活 Activity1並入棧,Activity2從 Active狀態轉換 Stoped狀態,Activity1. onActivityResult(int requestCode, int resultCode, Intent data)方法被執行,Activity2返回的數據通過data參數返回給Activity1。

Activity 棧

Android 是通過一種 Activity棧的方式來管理 Activity的,一個 Activity的實例的狀態決定它在棧中的位置。處於前台的 Activity總是在棧的頂端,當前台的 Activity因為異常或其它原因被銷毀時,處於棧第二層的 Activity將被激活,上浮到棧頂。當新的 Activity啟動入棧時,原 Activity會被壓入到棧的第二層。一個 Activity在棧中的位置變化反映了它在不同狀態間的轉換。

Activity 生命周期

在android.app.Activity類中,Android定義了一系列與生命周期相關的方法,在我們自己的 Activity中,只是根據需要復寫需要的方法,Java的多態性會保證我們自己的方法被虛擬機調用,這一點與 J2ME中的 MIDlet類似。

public class OurActivity extends Activity {

protected void onCreate(Bundle savedInstanceState);

protected void onStart();

protected void onResume();

protected void onPause();

protected void onStop();

protected void onDestroy();

}

這些方法的說明如下:

i.protected void onCreate(Bundle savedInstanceState)一個 Activity的實例被啟動時調用的第一個方法。一般情況下,我們都覆蓋該方法作為應用程序的一個入口點,在這裡做一些初始化數據、設置用戶界面等工作。大多數情況下,我們都要在這裡從xml 中加載設計好的用戶界面。例如:

setContentView(R.layout.main);

當然,也可從savedInstanceState中讀我們保存到存儲設備中的數據,但是需要判斷savedInstanceState是否為null,因為 Activity 第一次啟動時並沒有數據被存貯在設備中:

if(savedInstanceState!=null){

savedInstanceState.get("Key");

}

i.protected void onStart()該方法在 onCreate()方法之後被調用,或者在 Activity從 Stop狀態轉換為 Active狀態時被調用。

ii.protected void onResume()在 Activity從 Pause 狀態轉換到 Active 狀態

iii.protected void onStop()在 Activity從 Active 狀態轉換到 Stop 狀態時被調用。一般我們在這裡保存 Activity的狀態信息。

iv.protected void onDestroy()在 Active被結束時調用,它是被結束時調用的最後一個方法,在這裡一般做些釋放資源,清理內存等工作。

 

Activity 之間通信

使用 Intent 通信

在 Android中,不同的 Activity實例可能運行在一個進程中,也可能運行在不同的進程中。因此我們需要一種特別的機制幫助我們在 Activity 之間傳遞消息。Android中通過 Intent對象來表示一條消息,一個 Intent對象不僅包含有這個消息的目的地,還可以包含消息的內容,這好比一封 Email,其中不僅應該包含收件地址,還可以包含具體的內容。對於一個Intent 對象,消息“目的地”是必須的,而內容則是可選項。

在上面的實例中通過Activity. startActivity(intent)啟動另外一個 Activity的時候,我們在 Intent類的構造器中指定了“收件人地址”。

如果我們想要給“收件人”Activity說點什麼的話,那麼可以通過下面這封“e-mail”來將我們消息傳遞出去:

因為 Intent內部為我們准備好了一個bundle,所以我們也可以使用這種更為簡便的方法:

Intent intent =new Intent(EX06.this,OtherActivity.class);

intent.putExtra("boolean_key", true);

intent.putExtra("string_key", "string_value");

startActivity(intent);

接收:

Intent intent=getIntent();

intent.getBooleanExtra("boolean_key",false);

intent.getStringExtra("string_key");

使用 SharedPreferences

SharedPreferences 使用 xml格式為 Android 應用提供一種永久的數據存貯方式。對於一個 Android應用,它存貯在文件系統的/data/ data/your_app_package_name/shared_prefs/目錄下,可以被處在同一個應用中的所有 Activity 訪問。Android提供了相關的 API來處理這些數據而不需要程序員直接操作這些文件或者考慮數據同步問題。

// 寫入 SharedPreferences

SharedPreferences preferences = getSharedPreferences("name", MODE_PRIVATE);

Editor editor = preferences.edit();

editor.putBoolean("boolean_key", true);

editor.putString("string_key", "string_value");

editor.commit();

 

// 讀取 SharedPreferences

SharedPreferences preferences = getSharedPreferences("name", MODE_PRIVATE);

preferences.getBoolean("boolean_key", false);

preferences.getString("string_key", "default_value");

Activity 的 Intent Filter

Intent Filter 描述了一個組件願意接收什麼樣的 Intent對象,Android 將其抽象為 android.content.IntentFilter類。在 Android的 AndroidManifest.xml配置文件中可以通過節點為一個 Activity指定其 Intent Filter,以便告訴系統該Activity 可以響應什麼類型的Intent。

當程序員使用 startActivity(intent)來啟動另外一個 Activity時,如果直接指定 intent了對象的 Component屬性,那麼 Activity Manager將試圖啟動其 Component屬性指定的 Activity。否則Android 將通過Intent 的其它屬性從安裝在系統中的所有Activity 中查找與之最匹配的一個啟動,如果沒有找到合適的Activity,應用程序會得到一個系統拋出的異常。

Action 匹配

Action 是一個用戶定義的字符串,用於描述一個 Android應用程序組件,一個 Intent Filter可以包含多個 Action。在AndroidManifest.xml 的Activity 定義時可以在其節點指定一個 Action 列表用於標示 Activity所能接受的“動作”,例如:

……

 

如果我們在啟動一個 Activity時使用這樣的 Intent對象:

Intent intent =new Intent();

intent.setAction("com.zy.myaction");

那麼所有的 Action列表中包含了“com.zy.myaction”的 Activity都將會匹配成功。

Android 預定義了一系列的 Action分別表示特定的系統動作。這些 Action通過常量的方式定義在android.content. Intent中,以“ACTION_”開頭。我們可以在 Android 提供的文檔中找到它們的詳細說明。

URI 數據匹配

一個 Intent可以通過 URI 攜帶外部數據給目標組件。在節點中,通過節點匹配外部數據。

mimeType 屬性指定攜帶外部數據的數據類型,scheme指定協議,host、port、path指定數據的位置、端口、和路徑。如下:

android:host="host" android:port="port" android:path="path"/>

如果在 Intent Filter中指定了這些屬性,那麼只有所有的屬性都匹配成功時 URI數據匹配才會成功。

Category 類別匹配

節點中可以為組件定義一個 Category類別列表,當 Intent中包含這個列表的所有項目時 Category類別匹配才會成功。

一些關於 Activity 的技巧

鎖定 Activity 運行時的屏幕方向

Android 內置了方向感應器的支持。在 G1中,Android 會根據 G1 所處的方向自動在豎屏和橫屏間切換。但是有時我們的應用程序僅能在橫屏 /豎屏時運行,比如某些游戲,此時我們需要鎖定該 Activity運行時的屏幕方向,節點的android:screenOrientation屬性可以完成該項任務,示例代碼如下:

android:label="@string/app_name"

android:screenOrientation="portrait">// 豎屏 , 值為 landscape 時為橫屏

…………

 

全屏的 Activity

要使一個 Activity全屏運行,可以在其onCreate()方法中添加如下代碼實現:

// 設置全屏模式

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

WindowManager.LayoutParams.FLAG_FULLSCREEN);

// 去除標題欄

requestWindowFeature(Window.FEATURE_NO_TITLE);

在 Activity 的 Title 中加入進度條

為了更友好的用戶體驗,在處理一些需要花費較長時間的任務時可以使用一個進度條來提示用戶“不要著急,我們正在努力的完成你交給的任務”。如下圖:

在 Activity的標題欄中顯示進度條不失為一個好辦法,下面是實現代碼:

// 不明確進度條

requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

setContentView(R.layout.main);

setProgressBarIndeterminateVisibility(true);

 

// 明確進度條

requestWindowFeature(Window.FEATURE_PROGRESS);

setContentView(R.layout.main);

setProgress(5000);

 

Activity 的生命周期

和 J2ME 的 MIDlet 一樣,在android 中,Activity的生命周期交給系統統一管理。與 MIDlet不同的是安裝在 android中的所有的 Activity都是平等的。

Activity 的狀態及狀態間的轉換

在 android中,Activity 擁有四種基本狀態:

1.Active/Runing一個新 Activity啟動入棧後,它在屏幕最前端,處於棧的最頂端,此時它處於可見並可和用戶交互的激活狀態。

2.Paused當 Activity被另一個透明或者 Dialog樣式的 Activity覆蓋時的狀態。此時它依然與窗口管理器保持連接,系統繼續維護其內部狀態,所以它仍然可見,但它已經失去了焦點故不可與用戶交互。

3.Stoped當 Activity被另外一個 Activity覆蓋、失去焦點並不可見時處於Stoped狀態。

4.KilledActivity被系統殺死回收或者沒有被啟動時處於Killed狀態。

當一個 Activity實例被創建、銷毀或者啟動另外一個 Activity時,它在這四種狀態之間進行轉換,這種轉換的發生依賴於用戶程序的動作。下圖說明了 Activity 在不同狀態間轉換的時機和條件:

 

Android 程序員可以決定一個Activity 的“生”,但不能決定它的“死”,也就時說程序員可以啟動一個Activity,但是卻不能手動的“結束”一個Activity。當你調用Activity.finish()方法時,結果和用戶按下BACK 鍵一樣:告訴Activity Manager 該Activity 實例完成了相應的工作,可以被“回收”。隨後Activity Manager 激活處於棧第二層的Activity 並重新入棧,同時原Activity 被壓入到棧的第二層,從Active 狀態轉到Paused 狀態。例如:從Activity1 中啟動了Activity2,則當前處於棧頂端的是Activity2,第二層是Activity1,當我們調用Activity2.finish()方法時,Activity Manager重新激活 Activity1並入棧,Activity2從 Active狀態轉換 Stoped狀態,Activity1. onActivityResult(int requestCode, int resultCode, Intent data)方法被執行,Activity2返回的數據通過data參數返回給Activity1。

Activity 棧

Android 是通過一種 Activity棧的方式來管理 Activity的,一個 Activity的實例的狀態決定它在棧中的位置。處於前台的 Activity總是在棧的頂端,當前台的 Activity因為異常或其它原因被銷毀時,處於棧第二層的 Activity將被激活,上浮到棧頂。當新的 Activity啟動入棧時,原 Activity會被壓入到棧的第二層。一個 Activity在棧中的位置變化反映了它在不同狀態間的轉換。

Activity 生命周期

在android.app.Activity類中,Android定義了一系列與生命周期相關的方法,在我們自己的 Activity中,只是根據需要復寫需要的方法,Java的多態性會保證我們自己的方法被虛擬機調用,這一點與 J2ME中的 MIDlet類似。

public class OurActivity extends Activity {

protected void onCreate(Bundle savedInstanceState);

protected void onStart();

protected void onResume();

protected void onPause();

protected void onStop();

protected void onDestroy();

}

這些方法的說明如下:

i.protected void onCreate(Bundle savedInstanceState)一個 Activity的實例被啟動時調用的第一個方法。一般情況下,我們都覆蓋該方法作為應用程序的一個入口點,在這裡做一些初始化數據、設置用戶界面等工作。大多數情況下,我們都要在這裡從xml 中加載設計好的用戶界面。例如:

setContentView(R.layout.main);

當然,也可從savedInstanceState中讀我們保存到存儲設備中的數據,但是需要判斷savedInstanceState是否為null,因為 Activity 第一次啟動時並沒有數據被存貯在設備中:

if(savedInstanceState!=null){

savedInstanceState.get("Key");

}

i.protected void onStart()該方法在 onCreate()方法之後被調用,或者在 Activity從 Stop狀態轉換為 Active狀態時被調用。

ii.protected void onResume()在 Activity從 Pause 狀態轉換到 Active 狀態

iii.protected void onStop()在 Activity從 Active 狀態轉換到 Stop 狀態時被調用。一般我們在這裡保存 Activity的狀態信息。

iv.protected void onDestroy()在 Active被結束時調用,它是被結束時調用的最後一個方法,在這裡一般做些釋放資源,清理內存等工作。

 

Activity 之間通信

使用 Intent 通信

在 Android中,不同的 Activity實例可能運行在一個進程中,也可能運行在不同的進程中。因此我們需要一種特別的機制幫助我們在 Activity 之間傳遞消息。Android中通過 Intent對象來表示一條消息,一個 Intent對象不僅包含有這個消息的目的地,還可以包含消息的內容,這好比一封 Email,其中不僅應該包含收件地址,還可以包含具體的內容。對於一個Intent 對象,消息“目的地”是必須的,而內容則是可選項。

在上面的實例中通過Activity. startActivity(intent)啟動另外一個 Activity的時候,我們在 Intent類的構造器中指定了“收件人地址”。

如果我們想要給“收件人”Activity說點什麼的話,那麼可以通過下面這封“e-mail”來將我們消息傳遞出去:

因為 Intent內部為我們准備好了一個bundle,所以我們也可以使用這種更為簡便的方法:

Intent intent =new Intent(EX06.this,OtherActivity.class);

intent.putExtra("boolean_key", true);

intent.putExtra("string_key", "string_value");

startActivity(intent);

接收:

Intent intent=getIntent();

intent.getBooleanExtra("boolean_key",false);

intent.getStringExtra("string_key");

使用 SharedPreferences

SharedPreferences 使用 xml格式為 Android 應用提供一種永久的數據存貯方式。對於一個 Android應用,它存貯在文件系統的/data/ data/your_app_package_name/shared_prefs/目錄下,可以被處在同一個應用中的所有 Activity 訪問。Android提供了相關的 API來處理這些數據而不需要程序員直接操作這些文件或者考慮數據同步問題。

// 寫入 SharedPreferences

SharedPreferences preferences = getSharedPreferences("name", MODE_PRIVATE);

Editor editor = preferences.edit();

editor.putBoolean("boolean_key", true);

editor.putString("string_key", "string_value");

editor.commit();

 

// 讀取 SharedPreferences

SharedPreferences preferences = getSharedPreferences("name", MODE_PRIVATE);

preferences.getBoolean("boolean_key", false);

preferences.getString("string_key", "default_value");

Activity 的 Intent Filter

Intent Filter 描述了一個組件願意接收什麼樣的 Intent對象,Android 將其抽象為 android.content.IntentFilter類。在 Android的 AndroidManifest.xml配置文件中可以通過節點為一個 Activity指定其 Intent Filter,以便告訴系統該Activity 可以響應什麼類型的Intent。

當程序員使用 startActivity(intent)來啟動另外一個 Activity時,如果直接指定 intent了對象的 Component屬性,那麼 Activity Manager將試圖啟動其 Component屬性指定的 Activity。否則Android 將通過Intent 的其它屬性從安裝在系統中的所有Activity 中查找與之最匹配的一個啟動,如果沒有找到合適的Activity,應用程序會得到一個系統拋出的異常。

Action 匹配

Action 是一個用戶定義的字符串,用於描述一個 Android應用程序組件,一個 Intent Filter可以包含多個 Action。在AndroidManifest.xml 的Activity 定義時可以在其節點指定一個 Action 列表用於標示 Activity所能接受的“動作”,例如:

……

 

如果我們在啟動一個 Activity時使用這樣的 Intent對象:

Intent intent =new Intent();

intent.setAction("com.zy.myaction");

那麼所有的 Action列表中包含了“com.zy.myaction”的 Activity都將會匹配成功。

Android 預定義了一系列的 Action分別表示特定的系統動作。這些 Action通過常量的方式定義在android.content. Intent中,以“ACTION_”開頭。我們可以在 Android 提供的文檔中找到它們的詳細說明。

URI 數據匹配

一個 Intent可以通過 URI 攜帶外部數據給目標組件。在節點中,通過節點匹配外部數據。

mimeType 屬性指定攜帶外部數據的數據類型,scheme指定協議,host、port、path指定數據的位置、端口、和路徑。如下:

android:host="host" android:port="port" android:path="path"/>

如果在 Intent Filter中指定了這些屬性,那麼只有所有的屬性都匹配成功時 URI數據匹配才會成功。

Category 類別匹配

節點中可以為組件定義一個 Category類別列表,當 Intent中包含這個列表的所有項目時 Category類別匹配才會成功。

一些關於 Activity 的技巧

鎖定 Activity 運行時的屏幕方向

Android 內置了方向感應器的支持。在 G1中,Android 會根據 G1 所處的方向自動在豎屏和橫屏間切換。但是有時我們的應用程序僅能在橫屏 /豎屏時運行,比如某些游戲,此時我們需要鎖定該 Activity運行時的屏幕方向,節點的android:screenOrientation屬性可以完成該項任務,示例代碼如下:

android:label="@string/app_name"

android:screenOrientation="portrait">// 豎屏 , 值為 landscape 時為橫屏

…………

 

全屏的 Activity

要使一個 Activity全屏運行,可以在其onCreate()方法中添加如下代碼實現:

// 設置全屏模式

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

WindowManager.LayoutParams.FLAG_FULLSCREEN);

// 去除標題欄

requestWindowFeature(Window.FEATURE_NO_TITLE);

在 Activity 的 Title 中加入進度條

為了更友好的用戶體驗,在處理一些需要花費較長時間的任務時可以使用一個進度條來提示用戶“不要著急,我們正在努力的完成你交給的任務”。如下圖:

在 Activity的標題欄中顯示進度條不失為一個好辦法,下面是實現代碼:

// 不明確進度條

requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

setContentView(R.layout.main);

setProgressBarIndeterminateVisibility(true);

 

// 明確進度條

requestWindowFeature(Window.FEATURE_PROGRESS);

setContentView(R.layout.main);

setProgress(5000);

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved