Android四大組件--Activity詳解

來源:互聯網
上載者:User

本文的主要內容包括1、activity的建立、配置和使用;2、activity的跳轉和傳值;3、startActivityForResult;4、activity的生命週期。

1、activity的建立、配置和使用

Activity是一個應用中的組件,它為使用者提供一個可視的介面,方便使用者操作,比如說拔打電話、照相、發郵件或者是瀏覽地圖等。每個activity會提供一個可視的視窗,一般情況下這個視窗會覆蓋整個螢幕,但在某此情況下也會出現一些比螢幕小的視窗飄浮在另外一個視窗上面。

在 android 中建立一個 Activity 是很簡單的事情,編寫一個繼承自 android.app.Activity的 Java 類並在 AndroidManifest.xml聲明即可。下面是一個為了研究 Activity 生命週期的一個 Activity 執行個體:

public class Example extends Activity {      private static final String LOG_TAG = EX01.class.getSimpleName();      @Override      public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.main);          Log.e(LOG_TAG, "onCreate");      }      @Override      protected void onStart() {          Log.e(LOG_TAG, "onStart");          super.onStart();      }      @Override      protected void onResume() {          Log.e(LOG_TAG, "onResume");          super.onResume();      }      @Override      protected void onPause() {          Log.e(LOG_TAG, "onPause");          super.onPause();      }      @Override      protected void onStop() {          Log.e(LOG_TAG, "onStop");          super.onStop();      }      @Override      protected void onDestroy() {          Log.e(LOG_TAG, "onDestroy ");          super.onDestroy();      }  }  

PS1:

兩個最重要的方法是:
onCreate()--這個是必須實現的函數,在其中做初始化工作。記住:你必須在此函數中調用setContentView()函數的設定Activity的介面。
onPause()--這個雖然很重要,但不是要必須實現的。此函數在使用者離開Activity時被調用(這一般並不表示Activity要被銷毀了)。在這個函數中,你一般需要提交那些需儲存狀態的資料(因為使用者可能不再返回到這個Activity)

Android應用要求所有應用程式組件(Activity,Service,ContentProvider,BroadcastReceiver)都必須顯式進行配置,只要為元素添加子項目即可配置Activity。
如 AndroidManifest.xml (名單檔案,類似於Web應用中的web.xml檔案)
AndroidManifest.xml 中通過 節點說明 Activity,將 apk 檔案安裝後,系統根據這裡的說明來尋找讀取 Activity,本例中的說明如下:

                                             

PS2:
對於這個標籤中的內容如說明如下:
name:指定該Activity的實作類別
icon:指定該Activity的對應的表徵圖
label:指定該Activity的標籤
除此之外,配置Activity時通常還需要指定一個或多個元素,該元素用於指定該Activity可響應的Intent。
注意看,看到activity name的值中,最前面有個”.”,如果你把它忘了,程式運行就會出錯,而你很難找出錯誤的原因。

其次,不論你是Activity是只內部使用還是外部使用,都要去AndroidManifest.xml 名單檔案中註冊,否則依然會出現莫名其妙的錯誤,只是在內部使用時,不需要為acitivity增加意圖過濾器。

其中,
中就是過濾器。說明此Acitivity是程式的”main”入口,指出這個Acitivity需要在系統的應用列表中列出。
如果你寫的程式中的Activity不需被其它程式調用,那麼不需為這個Activity增加任何intent過慮器過濾器。但程式中必須有一個 Activity被指定為”main” Action和”launcher” category。你自己程中的 Activity可以用更直接的方式調用。

然而,如果你想讓你的Activity被其它程式調用,那麼你需要為它增加意圖過濾器。這些過意圖濾器包括,以及。這些元素指明了你的activity響應何種類型的 intent。關於intent過濾器,這裡不再詳細說明了。

2、Activity之間跳轉和傳值

前面我們瞭解了如何啟動一個Activity,一個Activity在啟動另外一個Activity的時候可能會遇到需要傳值的需要。Activity之間傳值是通過Bundle來實現的。

1)Activity跳轉介紹

最常見最一般的頁面跳轉代碼,很簡單,如下:

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


當然,OtherActivity同樣需要在 AndroidManifest.xml 中定義。

2)Bundle傳值介紹

1、如果資料比較少,比如只要傳一個名字,那麼只要j加一句"intent.putExtra("Name", "feng88724");"即可,代碼如下:

Intent intent = new Intent();intent.setClass(A.this, B.class);intent.putExtra("Name", "feng88724");startActivity(intent);

2、如果資料比較多,就需要使用 Bundle類了,代碼如下:

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

Intent intent =new Intent(CurrentActivity.this,OtherActivity.class);  // 建立一個帶“收件者地址”的 email   Bundle bundle =new Bundle();// 建立 email 內容  bundle.putBoolean("boolean_key", true);// 編寫內容  bundle.putString("string_key", "string_value");   intent.putExtra("key", bundle);// 封裝 email   startActivity(intent);// 啟動新的 Activity  

那麼“收件者”該如何收信呢?在 OtherActivity類的 onCreate()或者其它任何地方使用下面的代碼就可以開啟這封“e-mail”閱讀其中的資訊:

Intent intent =getIntent();// 收取 email   Bundle bundle =intent.getBundleExtra("key");// 開啟 email   bundle.getBoolean("boolean_key");// 讀取內容  bundle.getString("string_key");  


3、startActivityForResult用法詳解

有時,在頁面跳轉之後,需要返回到之前的頁面,同時要保留使用者之前輸入的資訊,這個時候該怎麼辦呢?

在頁面跳轉後,前一個Activity已經被destroy了。如果要返回並顯示資料,就必須將前一個Activity再次喚醒,同時調用某個方法來擷取並顯示資料。

要實現這個效果,需要做以下幾步:

1. 首先,從A頁面跳轉到B頁面時,不可以使用"startActivity()"方法,而要使用"startActivityForResult"方法。

2. 在A頁面的Activity中,需要重寫"onActivityResult"方法

onActivityResult(int requestCode, int resultCode, Intent data)

第一個參數:這個整數requestCode提供給onActivityResult,是以便確認返回的資料是從哪個Activity返回的。 這個requestCode和startActivityForResult中的requestCode相對應。
第二個參數:這整數resultCode是由子Activity通過其setResult()方法返回。

第三個參數:一個Intent對象,帶有返回的資料。

例如:

import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;public class MainActivity extends Activity {    private final static String TAG="MainActivity";        @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                Button btnOpen=(Button)this.findViewById(R.id.btnOpen);        btnOpen.setOnClickListener(new View.OnClickListener(){            public void onClick(View v) {                //得到新開啟Activity關閉後返回的資料                //第二個參數為請求碼,可以根據業務需求自己編號                startActivityForResult(new Intent(MainActivity.this, OtherActivity.class), 1);            }        });    }        /**     * 為了得到傳回的資料,必須在前面的Activity中(指MainActivity類)重寫onActivityResult方法     *      * requestCode 請求碼,即調用startActivityForResult()傳遞過去的值     * resultCode 結果碼,結果碼用於標識返回資料來自哪個新Activity     */    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        String result = data.getExtras().getString("result");//得到新Activity 關閉後返回的資料        Log.i(TAG, result);    }}

當新Activity關閉後,新Activity返回的資料通過Intent進行傳遞,android平台會調用前面Activity 的onActivityResult()方法,把存放了返回資料的Intent作為第三個輸入參數傳入,在onActivityResult()方法中使用第三個輸入參數可以取出新Activity返回的資料。

使用startActivityForResult(Intent intent, int requestCode)方法開啟新的Activity,新Activity關閉前需要向前面的Activity返回資料需要使用系統提供的setResult(int resultCode, Intent data)方法實現:

import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;public class OtherActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.other);        Button btnClose=(Button)findViewById(R.id.btnClose);        btnClose.setOnClickListener(new View.OnClickListener(){            public void onClick(View v) {                //資料是使用Intent返回                Intent intent = new Intent();                //把返回資料存入Intent                intent.putExtra("result", "My name is ting");                //設定返回資料                OtherActivity.this.setResult(RESULT_OK, intent);                //關閉Activity                OtherActivity.this.finish();            }        });            }}


setResult()方法的第一個參數值可以根據業務需要自己定義,上面代碼中使用到的RESULT_OK是系統Activity類定義的一個常量,值為-1,代碼片斷如下:

public class android.app.Activity extends ......{  public static final int RESULT_CANCELED = 0;  public static final int RESULT_OK = -1;  public static final int RESULT_FIRST_USER = 1;}

PS3:

請求碼的作用 :

使用startActivityForResult(Intent intent, int requestCode)方法開啟新的Activity,我們需要為startActivityForResult()方法傳入一個請求碼(第二個參數)。請求碼的值是根據業務需要由自已設定,用於標識請求來源。例如:一個Activity有兩個按鈕,點擊這兩個按鈕都會開啟同一個Activity,不管是那個按鈕開啟新Activity,當這個新Activity關閉後,系統都會調用前面Activity的onActivityResult(int requestCode, int resultCode, Intent data)方法。在onActivityResult()方法如果需要知道新Activity是由那個按鈕開啟的,並且要做出相應的業務處理:。


4、activity的生命週期

1、任務的概念:

任務其實就是activity 的棧它由一個或多個Activity組成的共同完成一個完整的使用者體驗,換句話說任務就是” 應用程式” (可以是一個也可以是多個,比如假設你想讓使用者看到某個地方的街道地圖。而已經存在一個具有此功能的activity 了,那麼你的activity 所需要做的工作就是把請求資訊放到一個Intent 對象裡面,並把它傳遞給startActivity()。於是地圖瀏覽器就會顯示那個地圖。而當使用者按下BACK 鍵的時候,你的activity 又會再一次的顯示在螢幕上,此時任務是由2個應用程式中的相關activity組成的)棧底的是啟動整個任務的Activity,棧頂的是當前啟動並執行使用者可以互動的Activity,當一個activity 啟動另外一個的時候,新的activity 就被壓入棧,並成為當前啟動並執行activity。而前一個activity 仍保持在棧之中。當使用者按下BACK 鍵的時候,當前activity 出棧,而前一個恢複為當前啟動並執行activity。棧中儲存的其實是對象,棧中的Activity 永遠不會重排,只會壓入或彈出,所以如果發生了諸如需要多個地圖瀏覽器的情況,就會使得一個任務中出現多個同一Activity 子類的執行個體同時存在。

2、任務中的所有activity 是作為一個整體進行移動的。整個的任務(即activity 棧)可以移到前台,或退至後台。舉個例子說,比如當前任務在棧中存有四個activity──三個在當前activity 之下。當使用者按下HOME 鍵的時候,回到了應用程式載入器,然後選擇了一個新的應用程式(也就是一個新任務)。則當前任務遁入後台,而新任務的根activity 顯示出來。然後,過了一小會兒,使用者再次回到了應用程式載入器而又選擇了前一個應用程式(上一個任務)。於是那個任務,帶著它棧中所有的四個activity,再一次的到了前台。當使用者按下BACK 鍵的時候,螢幕不會顯示出使用者剛才離開的activity(上一個任務的根activity)。取而代之,當前任務的棧中最上面的activity 被彈出,而同一任務中的上一個activity 顯示了出來。

3、Android系統是一個多任務(Multi-Task)的作業系統,可以在用手機聽音樂的同時,也執行其他多個程式。每多執行一個應用程式,就會多耗費一些系統記憶體,當同時執行的程式過多,或是關閉的程式沒有正確釋放掉記憶體,系統就會覺得越來越慢,甚至不穩定。

為瞭解決這個問題, Android 引入了一個新的機制-- 生命週期(Life Cycle)。

Android 應用程式的生命週期是由Android 架構進行管理,而不是由應用程式直接控制。通常,每一個應用程式(入口一般會是一個Activity 的onCreate 方法),都會產生一個進程(Process)。當系統記憶體即將不足的時候,會依照優先順序自動進行進程(process)的回收。不管是使用者或開發人員, 都無法確定的應用程式何時會被回收。所以為了很好的防止資料丟失和其他問題,瞭解生命週期很重要。

Activity整個生命週期的4種狀態、7個重要方法

1) 四種狀態

1. 活動(Active/Running)狀態
當Activity運行在螢幕前台(處於當前任務活動棧的最上面),此時它擷取了焦點能響應使用者的操作,屬於運行狀態,同一個時刻只會有一個Activity 處於活動(Active)或運行

(Running)狀態

1. 暫停(Paused)狀態
當Activity失去焦點但仍對使用者可見(如在它之上有另一個透明的Activity或Toast、AlertDialog等快顯視窗時)它處於暫停狀態。暫停Activity仍然是存活狀態(它保留著所有的狀態和成員資訊並保持和視窗管理器的串連),但是當系統記憶體極小時可以被系統殺掉

3. 停止(Stopped)狀態

完全被另一個Activity遮擋時處於停止狀態,它仍然保留著所有的狀態和成員資訊。只是對使用者不可見,當其他地方需要記憶體時它往往被系統殺掉

4. 非活動(Dead)狀態

Activity 尚未被啟動、已經被手動終止,或已經被系統回收時處於非活動的狀態,要手動終止Activity,可以在程式中調用"finish"方法。

如果是(按根據記憶體不足時的回收規則)被系統回收,可能是因為記憶體不足了

記憶體不足時,Dalvak 虛擬機器會根據其記憶體回收規則來回收記憶體:

1. 先回收與其他Activity 或Service/Intent Receiver 無關的進程(即優先回收獨

立的Activity)因此建議,我們的一些(耗時)後台操作,最好是作成Service的形式

2.不可見(處於Stopped狀態的)Activity

3.Service進程(除非真的沒有記憶體可用時會被銷毀)

4.非活動的可見的(Paused狀態的)Activity

5.當前正在運行(Active/Running狀態的)Activity

2)7個重要方法

當Activity從一種狀態進入另一狀態時系統會自動調用下面相應的方

法來通知使用者這種變化

當Activity第一次被執行個體化的時候系統會調用,

整個生命週期只調用1次這個方法

通常用於初始化設定: 1、為Activity設定所要使用的布局檔案2、為按鈕綁定監聽器等靜態設定作業

onCreate(Bundle savedInstanceState);

當Activity可見未獲得使用者焦點不能互動時系統會調用

onStart();

當Activity已經停止然後重新被啟動時系統會調用

onRestart();

當Activity可見且獲得使用者焦點能互動時系統會調用

onResume();

當系統啟動另外一個新的Activity時,在新Activity啟動之前被系統調用儲存現有的Activity中的持久資料、停止動畫等,這個實現方法必須非常快。當系統而不是使用者自己出於回收記憶體時,關閉了activity 之後。使用者會期望當他再次回到這個activity 的時候,它仍保持著上次離開時的樣子。此時用到了onSaveInstanceState(),方法onSaveInstanceState()用來儲存Activity被殺之前的狀態,在onPause()之前被觸發,當系統為了節省記憶體銷毀了Activity(使用者本不想銷毀)時就需要重寫這個方法了,當此Activity再次被執行個體化時會通過onCreate(Bundle savedInstanceState)將已經儲存的臨時狀態資料傳入因為onSaveInstanceState()方法不總是被調用,觸發條件為(按下HOME鍵,按下電源按鍵關閉螢幕,橫豎屏切換情況下),你應該僅重寫onSaveInstanceState()來記錄activity的臨時狀態,而不是持久的資料。應該使用onPause()來儲存持久資料。

onPause();

當Activity被新的Activity完全覆蓋不可見時被系統調用

onStop();

當Activity(使用者調用finish()或系統由於記憶體不足)被系統銷毀殺掉時系統調用,(整個生命週期只調用1次)用來釋放onCreate ()方法中建立的資源,如結束線程等

onDestroy();

PS4:

1、不設定Activity的android:configChanges時,切屏會重新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次

2、設定Activity的android:configChanges="orientation"時,切屏還是會重新調用各個生命週期,切橫、豎屏時只會執行一次

3、設定Activity的android:configChanges="orientation|keyboardHidden"時,切屏不會重新調用各個生命週期,只會執行onConfigurationChanged方法

4、當前Activity產生事件彈出Toast和AlertDialog的時候Activity的生命週期不會有改變

Activity運行時按下HOME鍵(跟被完全覆蓋是一樣的):onSaveInstanceState --> onPause --> onStop,再次進入啟用狀態時: onRestart -->onStart--->onResume

最後來談一下Activity和Servlet的相似和區別:

1、有過Web開發經驗的網友對 Servlet的概念應該比較熟悉了。實際上Activity對於Android應用有點類似於Servlet對於Web應用的作用,一個Web應用通常都需要多個Servlet組成,同樣,一個Android應用通常也需要多個Activity組成。對於Web應用而言,Servlet主要負責與使用者互動,並向使用者呈現應用狀態 ;對於Android應用而言,Activity大致也具有相同的功能。

2、相同點(部分):開發人員都無需建立他們的執行個體,無需調用他們的方法,這些由系統以回調的方式來調用,他們的額生命週期由外部進行管理。他們之間不能至今進行相互調用,所以不能進行直接的資料交換。

3、不同點:可以這樣說,一個是B/S模式,一個是C/S模式;Activity以組件來搭建介面,而Servlet則主要以IO流向瀏覽者產生文本響應。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.