一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

android.app.Activity 的介紹

 旭龍 2012-09-04


發(fā)現(xiàn)當前Android的資料不是很多,而且對于Activity的介紹也很少,所以把官方文檔的android.app.Activity的介紹翻譯了一下,加入了一些自己的理解。各位如果覺得我自己理解的不對,請無視。歡迎郵件討論。

android.app
public class

android.app.Activity

java.lang.Object

android.content.Context

android.app.ApplicationContext    ViewInflate.Factory

android.app.Activity      KeyEvent.Callback Window.Callback

 

 

Activity 是用戶唯一可以看得到的東西。幾乎所有的activity都與用戶進行交互,所以Activity主要負責的就是創(chuàng)建顯示窗口,你可以在這些窗口里使用setContentView(View)來顯示你自己的UI。activity展現(xiàn)在用戶面前的經(jīng)常是全屏窗口,你也可以將activity作為浮動窗口來使用(使用設置了windowIsFloating的主題),或者嵌入到其他的activity(使用ActivityGroup)中。下面是兩個幾乎所有Activity的子類都實現(xiàn)了的方法。

·         onCreate(Bundle) 這個方法是初始化 activity的地方. 最重要的是,你經(jīng)常需要在這里使用setContentView(int) 來設置UI布局所使用的layout資源, 當你需要使用程序控制UI中的組件時可以使用 findViewById(int) 來獲得對應的視圖。

·         當用戶離開activity時你可以在onPause() 進行相應的操作. 更重要的是,用戶做的任何改變都應該在該點上提交 (經(jīng)常提交到 ContentProvider 這里保存數(shù)據(jù))。

如果要使用 Context.startActivity()來啟動activity, activity都必須在啟動者應用包的AndroidManifest.xml文件中有對應的 <activity> 定義。

 

Activity類是 的一個重要部分。

這里涉及到的主題:

  1. Activity 生命周期
  2. 配置改變
  3. 啟動Activity并獲得結果
  4. 保存持久狀態(tài)
  5. 許可
  6. 進程生命周期

Activity 生命周期

系統(tǒng)中的Activity可以通過一個activity棧來進行管理。當一個新的activity啟動的時候,它首先會被放置在activity棧頂部并成為running狀態(tài)的activity —— 之前的activity也在activity棧中,但總是被保存在它的下邊,只有當這個新的activity退出以后之前的activity才能重新回到前景界面。

 

所有的activity本質(zhì)上有四種狀態(tài):

  • activity在屏幕的前景中(activity棧的頂端),它是active或者running狀態(tài)。
  • activity失去了焦點但是仍然可見(這個activity頂上遮擋了一個透明的或者非全屏的activity),它的狀態(tài)是paused。一個paused狀態(tài)的activity完全是alive的(它維護自己所有的狀態(tài)和成員信息,而且仍然在window manager的管理中),但當系統(tǒng)內(nèi)存極度貧乏時也會將其killed。
  • activity由于其他的activity而完全變暗,它就進入了stopped狀態(tài)。它仍然保持著所有的狀態(tài)和成員的信息,可是,他對于用戶來說不可見,當別的地方需要內(nèi)存的時候它經(jīng)常會被killed
  • activitypaused或者stopped,系統(tǒng)需要將其清理出內(nèi)存的時可以命令其finish或者簡單kill其進程。當它重新在用戶面前顯示的時候,它必須完全重新啟動并且將其關閉之前的狀態(tài)全部恢復回來。

下面的圖表是Activity的狀態(tài)圖,直角矩形代表了callback方法,你可以實現(xiàn)這些方法從而使Activity在改變狀態(tài)的時候執(zhí)行你制定的操作。帶顏色的橢圓形是Activity的主要狀態(tài)。

activity lifecycle

 

這里有三個比較關鍵的生命周期。

  • 從最初調(diào)用onCreate(Bundle)到最終調(diào)用onDestroy()稱為完整生命周期Activity會在onCreate()進行所有“全局”狀態(tài)的設置,在onDestroy()中釋放所有持有的資源。舉個例子,如果它有一個從網(wǎng)絡上下載數(shù)據(jù)的后臺線程,那他可能就會在onCreate()中創(chuàng)建這個線程并在onDestroy()中停止這個線程。
  • activity調(diào)用onStart()開始,到調(diào)用對應的onStop()為止稱為可見生命周期。在這段時間內(nèi)用戶可以在屏幕上看到這個activity,盡管并不一定是在前景也不一定可以和用戶交互。在這兩個方法之間你可以維護那些activity在用戶顯示時所需的資源。舉個例子來說,你可以在onStart()中注冊一個IntentReceiver來監(jiān)控那些可以對你的UI產(chǎn)生影響的環(huán)境改變,當你的UI不繼續(xù)在用戶面前顯示時你可以在onStop()中注銷這個IntentReceiver。每當activity在用戶面前顯示或者隱藏時都會調(diào)用相應的方法,所以onStart()onStop()方法在整個生命周期中可以多次被調(diào)用。
  • activity調(diào)用onResume()開始,到調(diào)用對應的onPause()為止稱為前景生命周期,這段時間activity處于其他所有activity的前面,且與用戶交互。一個activity可以經(jīng)常在resumedpaused狀態(tài)之間轉(zhuǎn)換——例如手機進入休眠時、activity的結果返回時、新的intent到來時——所以這兩個方法中的代碼應該非常的簡短。

下面的Activity方法定義了activity完整的生命周期。他們?nèi)际?/span>hook方法,你可以重載這些方法從而使activity在狀態(tài)改變時執(zhí)行你所期望的操作。所有activity都應該實現(xiàn)自己的onCreate(Bundle)方法來進行初始化設置;大部分還應該實現(xiàn)onPause()方法提交數(shù)據(jù)的修改并且準備終止與用戶的交互。盡管我們計劃在系統(tǒng)中添加更多的工具來管理應用,現(xiàn)在大多activity仍需要實現(xiàn)onFreeze()并且在onCreate(Bundle)中執(zhí)行對應的狀態(tài)恢復。其他的方法可以在需要時進行實現(xiàn),當實現(xiàn)這些方法的時候需要注意的是一定要調(diào)用父類中的對應方法。

 

public class Activity extends ApplicationContext {
     
protected void onCreate(Bundle icicle);
     
protected void onStart();
     
protected void onRestart();
     
protected void onResume();
     
protected void onFreeze(Bundle outIcicle);
     
protected void onPause();
     
protected void onStop();
     
protected void onDestroy();
 
} 

 

一般來說activity的生命周期變化看起來比較象下面的表格:

 

(此處譯者進行了大塊的修改,請參考原文閱讀下面表格)


方法

描述

Killable?

下一方法

onCreate()

Activity初次創(chuàng)建時被調(diào)用,你應該在這里進行一般的靜態(tài)設置:創(chuàng)建view、將數(shù)據(jù)綁定到list等等。如果activity之前存在凍結狀態(tài),那么此狀態(tài)將在Bundle中提供。

如果activity首次創(chuàng)建,本方法后將會調(diào)用onStart(),如果activity是停止后重新顯示,則將調(diào)用onRestart()。

No

onStart() or onRestart()

 

onStart()

activity對用戶即將可見的時候調(diào)用。

其后調(diào)用onRestart()onResume()(框架是否進行選擇性調(diào)用onResume()僅僅是猜測)

No

onRestart() or onResume()

onRestart()

activity從停止狀態(tài)重新啟動時調(diào)用。其后調(diào)用onResume()。

No

onResume()

 

onResume()

activity將要與用戶交互時調(diào)用此方法,此時activityactivity棧的棧頂,用戶輸入已經(jīng)可以傳遞給它。

如果其他的activity在它的上方恢復顯示,則將調(diào)用onFreeze()。

No

onFreeze()

onFreeze()

當你的activity被暫停而其他的activity恢復與用戶交互的時候這個方法會被調(diào)用(在其他activity顯示之前),你可以使用這個方法保存你當前的用戶狀態(tài)(一般來說是當前實例的用戶狀態(tài))。暫停之后,為了回收資源供給前景activity,系統(tǒng)會在需要的時間停止(或者kill)你的應用。以后如果你的activity啟動一個新的實例重新與用戶進行交互,你保存在這里的狀態(tài)都將通過onCreate()方法傳遞給新的實例。

其后總是調(diào)用onPause()方法。

No

onPause()

onPause()

當系統(tǒng)要啟動一個其他的activity時調(diào)用(其他的activity顯示之前),這個方法被用來提交那些持久數(shù)據(jù)的改變、停止動畫、和其他占用CPU資源的東西。由于下一個activity在這個方法返回之前不會resumed,所以實現(xiàn)這個方法時代碼執(zhí)行要盡可能快。

如果activity重新回到前景時將調(diào)用onResume(), 如果對用戶徹底不可見則會調(diào)用onStop()。

Yes

onResume() or
onStop()

onStop()

當另外一個activity恢復并遮蓋住此activity,導致其對用戶不再可見時調(diào)用。一個新activity啟動、其它activity被切換至前景、當前activity被銷毀時都會發(fā)生這種場景。

activity重新回到前景與用戶交互時調(diào)用onRestart(),如果activity將退出則調(diào)用onDestory()。

Yes

onStart() or
onDestroy()

onDestroy()

在你的activity被銷毀前所調(diào)用的最后一個方法,當進程終止時會出現(xiàn)這種情況(對activity直接調(diào)用finish()方法或者系統(tǒng)為了節(jié)省空間而臨時銷毀此activity的實例,你可以通過isFinishing()的返回值來區(qū)分這兩種情況)。

Yes

nothing


: 這個表格本人覺得還有些值得商榷的地方,建議作為參考閱讀,不管是原文還是譯文。

 

注意上表中“Killable”這一列 —— 對于那些標記killable的方法,當這些方法結束后,activity的進程可能在任何時間被系統(tǒng)kill而不再執(zhí)行activity中的任何代碼。因此你應該利用onFreeze()(保存你當前UI的狀態(tài))和onPause()(將所有的修改寫回持久存儲),這樣activity才能在被kill的時候正確的保存當前的狀態(tài)。如果需要了解一個進程的生命周期與他所執(zhí)行的activity之間的關系 參見 進程生命周期 部分。

 

       對于那些標記killable的方法,從這些方法啟動開始直到返回之前,activity的進程都不回被系統(tǒng)kill。舉個例子,一個activityonPause()方法返回后處于killable的狀態(tài),這種狀態(tài)會一直持續(xù)到onResume()方法開始執(zhí)行。

 

配置改變

如果設備的配置(在Resources.Configuration中進行了定義)發(fā)生改變,那么所有用戶界面上的東西都需要進行更新,以適應新的配置。因為Activity是與用戶交互的最主要的機制,它包含了處理配置改變的專門支持。

 

       除非你特殊指定,否則當配置發(fā)生改變(比如屏幕方向、語言、輸入設備等等的改變)時你當前的activity都將被銷毀,這銷毀是通過一個正常的activity生命周期過程(onFreeze(Bundle), onPause(), onStop(), onDestroy())進行的。如果activity之前正在前景畫面,當這個實例的onDestroy()調(diào)用完成后將會啟動這個activity的一個新的實例,并將前面那個實例中onFreeze(Bundle)所保存的內(nèi)容傳遞給新的實例。

 

因為任何的應用資源(包括layout文件)都有可能由于任何配置值而改變。因此處理配置改變的唯一安全的方法就是重新獲取所有的資源,包括layout、繪圖資源(原文drawables)、字符串資源。由于activity已經(jīng)如何保存自己的狀態(tài)并從這些狀態(tài)中重建自身,所以activity重新啟動自身來獲得新的配置將是一個非常便利的途徑。

 

       在一些特殊的情況中,你可能希望當一種或者多種配置改變時避免重新啟動你的activity。你可以通過在manifest中設置android:configChanges屬性來實現(xiàn)這點。你可以在這里聲明activity可以處理的任何配置改變,當這些配置改變時不會重新啟動activity,而會調(diào)用activityonConfigurationChanged(Resources.Configuration)方法。如果改變的配置中包含了你所無法處理的配置(在android:configChanges并未聲明),你的activity仍然要被重新啟動,而onConfigurationChanged(Resources.Configuration)將不會被調(diào)用。

 

啟動Activity并獲得結果

startActivity(Intent)方法可以用來啟動一個新的activity,這個activity將被放置在activity棧的棧頂。這個方法只有一個參數(shù)Intent,這個參數(shù)描述了將被執(zhí)行的activity。

 

       有時候你希望在一個activity結束時得到它返回的結果。舉個例子,你可能啟動一個activity來讓用戶從通訊簿中選擇一個人;當它結束的時候?qū)祷剡@個所選擇的人。為了得到這個返回的信息,你可以使用startSubActivity(Intent, int)這個方法來啟動新的activity,第二個整形參數(shù)將會作為這次調(diào)用的識別標記。這個activity返回的結果你可以通過onActivityResult(int, int, String, Bundle)方法來獲得,此方法的第一個參數(shù)就是之前調(diào)用所使用的識別標記。

 

       activity退出的時候,它可以調(diào)用setResult(int)來將數(shù)據(jù)返回給他的父進程。這個方法必須提供一個結果碼,這個結果碼可以使標準結果RESULT_CANCELED, RESULT_OK,也可以是其他任何從RESULT_FIRST_USER開始的自定義值。此外,它還可以返回一段字符串(經(jīng)常是一段數(shù)據(jù)的URL地址),一個包含它所有希望值的Bundle。這些信息都會在父activity的回調(diào)函數(shù)Activity.onActivityResult()中出現(xiàn),并連同最初提供的識別標記一起(此處有些拗口,意思其實就是子activity返回的內(nèi)容、返回碼、識別標記都將作為參數(shù),按照不同的返回情況來調(diào)用父activityActivity.onActivityResult()方法,以實現(xiàn)出現(xiàn)各種返回時父activity做出響應的處理)。

 

       如果子activity由于某種情況發(fā)生失敗(例如crashing),父activity將會收到RESULT_CANCELED結果碼。

 

       這里是一個例子,說明了如何啟動一個新的activity并處理結果。

 

public class MyActivity extends Activity {
     
...
     
static final int PICK_CONTACT_REQUEST = 0;
     
public boolean onKeyDown(int keyCode, KeyEvent event) {
         
if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
             
// When the user center presses, let them pick a contact.
             startSubActivity
(
                 
new Intent(Intent.PICK_ACTION,
                 
Uri.parse("content://contacts")),
                 PICK_CONTACT_REQUEST
);
           
return true;
         
}
         
return false;
     
}
     
protected void onActivityResult(int requestCode, int resultCode,
             
String data, Bundle extras) {
         
if (requestCode == PICK_CONTACT_REQUEST) {
             
if (resultCode == RESULT_OK) {
                 
// A contact was picked.  Here we will just display it
                 
// to the user.
                 startActivity
(new Intent(Intent.VIEW_ACTION,
                     
Uri.parse(data)));
             
}
         
}
     
}
 
}


當一個按鍵被按下時onKeyDown()啟動一個新的activity。當新的activity結束后onActivityResult()會被調(diào)用。

保存持久狀態(tài)

一般來說有兩類持久狀態(tài)需要activity來處理:類似于文檔的共享數(shù)據(jù)(一般使用content provider存儲在SQLite數(shù)據(jù)庫中)和就像用戶參數(shù)設定一樣的內(nèi)部狀態(tài)。

 

       對于content provider的數(shù)據(jù),我們建議activity使用“編輯即發(fā)生”用戶模型。就是說,用戶所做的任何編輯都將立即生效而不要求任何進一步的確認。下面兩條規(guī)則可以使支持這種模型成為一件簡單的事情。

·         創(chuàng)建一個新文檔的時候,立即為它創(chuàng)建文件或者后臺數(shù)據(jù)庫條目。舉例來說,如果用戶要寫一封新郵件,當他們開始輸入的時候馬上創(chuàng)建一個新的數(shù)據(jù)庫條目,所以即使他們輸入以后進入別的activity,這封郵件也會在草稿箱中出現(xiàn)。

·         activityonPause()方法被調(diào)用時,它應該將任何用戶所做修改向后臺的content provider 或者文件提交。這可以確保即將運行的其他activity可以看到這些修改。你可能會使用更激進的方式來在你的activity生命周期中關鍵的時間點上提交數(shù)據(jù):例如在啟動一個新的activity之前、終止你的activity之前、當用戶在輸入域之間切換時,等等。(譯者注:根據(jù)文檔的其他部份,個人覺得啟動新activity之前及終止當前activity之前進行保存的說法都值得商榷,具體位置仍可能是在onPause())

這個模型是為了避免用戶在activity之間切換時數(shù)據(jù)丟失而設計的,同時允許系統(tǒng)在activity處于paused狀態(tài)后任何時間都可以安全的kill這個activity(因為其它地方可能需要系統(tǒng)資源)。注意這隱含著一個含義,即用戶點擊你activityBACK鍵并不意味著“取消”——它意味著保存他當前的內(nèi)容并離開你的activity。Activity中取消編輯必須通過其他機制來提供,例如顯式的提供"revert" "undo"選項。

 

如果需要了解更多關于content providers的信息,參見content package。這是不同的activity之間如何調(diào)用和彼此之間傳遞數(shù)據(jù)的關鍵。

 

Activity同時提供了API來管理與activity相關聯(lián)的內(nèi)部持久狀態(tài)。這可以用來記憶用戶日歷的首選初始顯示(日期視圖或者周視圖)或者用戶web瀏覽器的缺省主頁這類信息。

 

       Activity持久狀態(tài)使用getPreferences(int)方法來管理,允許你取得和修改一系列與activity相關聯(lián)的名稱/取值對。如果要在應用的多個組件(activities,recivers,services,providers)之間共享參數(shù),你可以使用底層方法Context.getSharedPreferences()來獲得存儲在一個特定名稱下的參數(shù)對象。(注意:在application packages之間不能共享設置數(shù)據(jù) —— 如果要這么做的話你需要使用content provider)。

 

這里摘錄了一段日歷activity中的代碼,用來在永久設定中保存用戶首選的視圖模式。


public class CalendarActivity extends Activity {
     ...
     static final int DAY_VIEW_MODE = 0;
     static final int WEEK_VIEW_MODE = 1;
     private SharedPreferences mPrefs;
     private int mCurViewMode;

     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         SharedPreferences mPrefs = getSharedPreferences();
         mCurViewMode = mPrefs.getInt("view_mode" DAY_VIEW_MODE);
     }

     protected void onPause() {
         super.onPause();
         SharedPreferences.Editor ed = mPrefs.edit();
         ed.putInt("view_mode", mCurViewMode);
         ed.commit();
     }
 }

許可

你可以通過在Activity所屬應用的manifest文件中對應的<activity>標簽中進行聲明來限制哪些應用可以啟動此Activity。如果你進行了聲明,其它應用需要在他們自己的manifest文件中聲明對應的<uses-permission>元素(而且需要在安裝時被授予許可:譯者注)才可以啟動這個activity。

 

如果需要了解更多有關于一般安全機制和許可方面的信息可以參考Security Model。

進程生命周期

Android系統(tǒng)會盡量久的保留應用進程。但是當內(nèi)存降低時最終還是要移除舊的進程。就像Activity 生命周期 中描述的一樣,移除哪個進程還是要取決于關聯(lián)的用戶與之交互的程度。一般來說,進程可以基于其中運行的activity所處的生命周期而分成四種狀態(tài),下面將這些狀態(tài)根據(jù)重要程度排列。系統(tǒng)會在kill更重要的進程(第一個)之前首先kill那些不那么重要的進程(最后一個)。

 

1.     前景activity(處于屏幕最上方,用戶與之交互的activity)被認為是最重要的。如果設備上的內(nèi)存無法滿足它的使用,Kill此進程只能作為最后的手段。一般來說這個時候設備處于內(nèi)存paging狀態(tài),為了使用戶界面保持響應才會發(fā)出這個kill請求。

2.     可見activity(一個對用戶可見,但是不在前景的activity,比如處在浮動對話框后)被認為是非常重要的,除非為了保證前景activity運行,否則不會被kill。

3.     后臺activity(一個對用戶不可見,并處于paused狀態(tài)的activity)就不再重要了,所以當需要為其它前景的或者可見的activity運行而回收內(nèi)存時系統(tǒng)可以很安全的kill它們。

4.     空進程是一個沒有運行activity或者其他應用組件(比如Service或者IntentReceiver類)的進程。當內(nèi)存開始降低時系統(tǒng)很快就會kill掉這些進程。因此當你要在activity外運行任何的后臺操作時,必須在IntentReceiverService的上下文環(huán)境中運行,這樣系統(tǒng)才知道需要將你的進程保留而不是kill。

有些時候Activity可能需要長時間運行一個操作,且它并不依賴于activity的生命周期而存在。例如一個照相機應用可能允許你將照片上傳到web站點。上傳可能需要很長時間,在上傳過程中應該允許用戶離開這個應用。為了做到這一點,你的activity應該在上傳時啟動一個Service來執(zhí)行此工作。這將使系統(tǒng)在你的進程上傳數(shù)據(jù)的過程中能夠恰當?shù)膮^(qū)分它的優(yōu)先級(認為此進程比其他不可見應用更重要),不管原來的activity的狀態(tài)是paused、stopped還是finished。

 

文章可隨意轉(zhuǎn)載,但務必注明出處
marshal.hird@gmail.com

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    亚洲专区一区中文字幕| 欧美中文字幕日韩精品| 欧美一区二区日韩一区二区| 国产毛片不卡视频在线| 日本不卡在线视频你懂的 | 亚洲另类女同一二三区| 亚洲一区二区三区四区| 免费在线播放不卡视频| 欧美日不卡无在线一区| 国产又猛又黄又粗又爽无遮挡 | 国产av大片一区二区三区 | 搡老熟女老女人一区二区| 老鸭窝老鸭窝一区二区| 女厕偷窥一区二区三区在线| 国产免费人成视频尤物| 日本人妻丰满熟妇久久| 好吊妞视频只有这里有精品| 欧美一区二区口爆吞精| 国产福利在线播放麻豆| 日韩中文高清在线专区| 久久99夜色精品噜噜亚洲av| 国产精品熟女乱色一区二区| 东京热一二三区在线免| 99久久国产综合精品二区| 国产亚洲视频香蕉一区| 欧美乱妇日本乱码特黄大片| 日韩精品第一区二区三区| 欧美欧美欧美欧美一区| 国产精品激情在线观看| 日韩偷拍精品一区二区三区 | 日本视频在线观看不卡| 国产欧美一区二区久久| 亚洲一区二区三区福利视频| 精品女同一区二区三区| 成人精品欧美一级乱黄| 内用黄老外示儒术出处| 亚洲美女国产精品久久| 91久久精品国产一区蜜臀| 又色又爽又无遮挡的视频| 亚洲国产成人爱av在线播放下载| 久久国产亚洲精品赲碰热|