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

Android四大組件--Activity詳解

編輯:關於Android編程

本文的主要內容包括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流向浏覽者生成文本響應。

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