Android開發之Activity詳解_Android

來源:互聯網
上載者:User

Activity

  一個Activity是一個應用程式組件,提供一個螢幕,使用者可以用來互動為了完成某項任務,例如撥號、拍照、發送email、看地圖。每一個activity被給予一個視窗,在上面可以繪製使用者介面。視窗通常充滿螢幕,但也可以小於螢幕而浮於其它視窗之上。

  一個應用程式通常由多個activities組成,他們通常是松耦合關係。通常,一個應用程式中的activity被指定為"main"activity,當第一次啟動應用程式的時候呈現給使用者的那個activity。每一個activity然後可以啟動另一個activity為了完成不同的動作。每一次一個activity啟動,前一個activity就停止了,但是系統保留activity在一個棧上(“back stack”)。當一個新activity啟動,它被推送到棧頂,取得使用者焦點。Back Stack符合簡單“後進先出”原則,所以,當使用者完成當前activity然後點擊back按鈕,它被彈出棧(並且被摧毀),然後之前的activity恢複。

  當一個activity因新的activity啟動而停止,它被通知這種狀態轉變通過activity的生命週期回呼函數。有許多回呼函數一個activity可能會收到,源於它自己的狀態變化-無論系統建立它、停止它、恢複它、摧毀它-並且每個回調提供你完成適合這個狀態的指定工作的機會。例如,當停止的時候,你的activity應該釋放任何大的對象,例如網路資料庫串連。當activity恢複,你可以重新獲得必要的資源和恢複被中斷的動作。這些狀態轉換都是activity的生命週期的部分。

Creating an Activity

  建立一個activity,你必須建立一個Activity的子類(或者一個Activity的子類的子類)。在你的子類中,你需要實現系統回調的回調方法,當activity在它的生命週期的多種狀態中轉換的時候,例如當activity被建立、停止、恢複或摧毀。兩個最重要的回調方法是:
onCreate()
    你必須實現這個方法。系統調用它當建立你的activity的時候。在你的實現中,你應該初始化你的activity的基本的組件。更重要的是,這裡就是你必須調用setContentView()來定義activity使用者介面而已的地方。
onPause()
    系統調用這個方法當使用者離開你的activity(雖然不總是意味著activity被摧毀)。這通常是你應該提交任何變化,那此將會超越user session而存在的(因為使用者可能不再回來)。

  有若干其它生命週期回呼函數你應該使用為了提供一個流暢的使用者體驗,並表操作異常中斷會引起你的activity被中斷甚至被摧毀。

1、Implementing a user interface

  一個activity的使用者介面被一個層次化的視圖提供--繼承於View類的對象。每個View控制activity視窗中的一個特定矩形地區並且能響應使用者互動。例如,一個view可能是個button,初始化動作當使用者觸摸它的時候。

  Android提供大量預定義的view,你可以使用來設計和組件你的布局。“Widgets”是一種給螢幕提供可視化(並且互動)元素的view,例如按鈕、檔案域、複選框或者僅僅是映像。“Layouts”是繼承於ViewGroup的View,提供特殊的布局模型為它的子view,例如線程布局、格子布局或相關性布局。你可以子類化View和ViewGroup類(或者存在的子類)來建立自己的widget和而已並且應用它們到你的activity布局中。

  最普通的方法是定義一個布局使用view加上XML布局檔案儲存在你的程式資源裡。這樣,你可以單獨維護你的使用者介面設計,而與定義activity行為的代碼無關。你可以設定布局作為UI使用setContentView(),傳遞資源布局的資源ID。可是,你也可以建立新Views在你的activity代碼,並且建立一個view層次通過插入新Views到ViewGroup,然後使用那個布局通過傳遞到根ViewGroup給setContentView()。

Declaring the activity in the manifest

  你必須聲明你的activity在manifest檔案為了它可以被系統訪問。要聲明你的activity,開啟你的manifest檔案,添加一個<activity>元素作為<application>元素的子項目。例如:

Using intent filters

  一個<activity>元素也能指定多種intent filters--使用<inetent-filter>元素--為了聲明其它應用程式可以啟用它。

  當你建立一個新應用程式使用Android SDK工具,存根activity自動為你建立,包含一個intent filter,聲明了activity響應"main"動作,並且應該被 放置 在"launcher"分類。Intent filter看起來像這個樣子。

  <action>元素指定這是一個"main"進入點對這個應用程式。<category>元素指定,這個activity應該被列入系統應用程式列表中(為了允許使用者啟動這個activity)。

  如果你希望應用程式自包含,並且不希望別的應用程式啟用它的activities,那麼你不需要任何其它intent filters。只有一個activity應該有“main"動作和”launcher“分類,就像前面這個例子。你不希望被其它應用程式訪問原Activities應該沒有intent filters而且你能啟動他們通過自己顯示的intent。

  可是,如果你希望你的activity響應影含的intents,從其它應用程式(和你自己的),那麼你必須定義額外的intent filters為這個activity。每一種你希望響應的類型的intent,你必須包含<intent-filter>,包含<action>元素,可選的,一個<category>元素並且/或一個<data>元素。這些元素指定你的activity能響應的intent的類型。

Starting an Activity

  你可以開啟另一個activity通過startActivity(),傳遞一個Intent描述了你希望啟動的Activity。Intent指定要麼準備的activity你希望啟動或描述你希望完成的動作(作業系統選擇合適的activity為你,可能來自定不同的應用程式)。一個intent可以傳輸小量資料被啟動的activity使用。

  完全工作在你的應用程式之內,你將經常需要簡單的啟動一個未知的activity。你可以這麼通過建立一個intent顯示的定義你希望啟動的activity,使用類名。例如,下面顯示一個activity怎麼啟動另一個activity命名為SignInActivity:

  可是,你的應用程式或許希望執行一些動作,例如發送一份郵件、檔案訊息或者狀態更新,使用你的activity的資料。在這種情況下,你的應用程式或許沒有它自己的activity來完成這個動作,因此你可以促使裝置上其它應用程式提供的activity來完成你的動作。這才是intent真正有價值的地方--你可以建立一個intent描述一個你希望執行的動作,然後系統啟動一個合適的activity從其它應用程式。如果有多種activities可以處理這個intent,那麼 使用者可以選擇哪一個來執行。例如,如果你希望允許使用者發送郵件,你可以建立下面的Intent: 

  EXTRA_EMAIL額外的添加給intent一個字串數組指定email地址,當一個郵件應用程式響應這個intent的時候,它讀取這些字串數組並且放置他們到相應欄位。在這種情況下,email應用程式的activity啟動並且當使用者執行完,你的activity恢複。

Starting an activity for a result

  有時,你或許希望接收一個結果從你啟動的activity。在這種情況下,開啟這個activity通過startActivityForResult()(而不是startActivity())。然後從隨後的activity接收結果,實現onActiviryResult()回呼函數。當隨後的activity完成,它返回一個結果給你的onActivityResult()函數通過一個intent。

  例如,或許你希望使用者選擇他們中的一個連絡人,所以你的activity可以對這個連絡人做些事情。下面是你怎麼建立這樣一個Intent和操作結果:

  這個例子展現了基本的邏輯你應該使用的在你的onActivityResult()函數中,為了操作一個activity的結果。第一個條件檢測是否請求成功--如果是,那麼 resultCode將會是RESULT_OK--並且是否這個請求是否是這個響應是響知道--在這種情況下,requestCode匹配第二個參數用startActivityForResult()的參數。在那裡,代碼操作activity結果通過查詢返回在intent中的資料(data參數)。

  將發生的是,一個ContentResolver實現查詢content provider,返回一個Cursor允許讀查詢的資料。

Shut Down an Activity

  你可以關閉一個activity通過調用自身的finish()方法。你也可以關閉一個獨立的activity你之前啟動的通過finiActivity()。

  注意:在大多數情況下,你不應該顯示結果一個activity使用這些方法。正在下文所討論的關於activity的生命週期,Android系統管理一個activity的生命週期為你,所以你不需要結果你自己的activity。調用這些函數對使用者體驗有害並且只有在你決對不希望使用者返回到這個activity的情況下。

Managing the Activity Lifecycle

  管理你的activity的生命週期通過實現回呼函數非常關鍵對開發一個健壯和有彈性的應用程式。一個activity的生命週期直接被與其相關聯的其它activity影響,task和bask stack。

  一個activity可以存在於主要的三種狀態:

  1、Resumed

    activity在前景並且擁有使用者焦點。(這個狀態有時也叫”running“)

  2、Paused

    另一個activity在前景並且擁有使用者焦點,但這個仍然可見。也就是說,另一個activity可見在這個的上面,當前activity部分透明或沒有覆蓋整個螢幕。一個paused activity完全活著(the Activity對象維在記憶體中,它維護所有的狀態並且記憶資訊,仍然串連著視窗管理器),但是可以被系統殺死在極端需要記憶體的情形下。

  3、Stopped

    一個activity被另一個activity完全阻擋(activity現在在後台)。一個stopped activity仍然活著(Activity object維持在記憶體中,它維擴所有的狀態和成員資訊,但沒有綁定視窗管理器)。可是,它不再被使用者可見並且它可被系統銷毀在需要的地方。
  如果一個activity paused或者stopped,系統可以從記憶體中拋棄它通過要求它結束(調用它的finish()方法),或者簡單的殺掉它的進程。當activity再次被開啟(在被finished或殺死後),它重建立立所有的東西。

Implementing the lifecycle callbacks

  當一個activity轉換到或轉換出上面提到的狀態,它被通過各種不同的回呼函數通知。所有這些回呼函數都是hook,你可以覆蓋來做合適的工作當你的activity狀態變化。下面的activity骨架包含每一個基本的生命週期函數:

  注意:你的這些生命週期函數的實現必須調用父類的實現在你做自己的工作之前,就像上面顯示的一樣。

  放在一起,這些函數定義了整個生命週期關於一個activity。通過實現這些方法,你可以監視三種嵌套的迴圈在activity生命週期中。
  1、一個activity的整個生命時間發生在onCreate()和onDestroy()函數。你的activity應該設定全域狀態(例如定義布局)在onCreate(),並且釋放所有的資源在onDestroy()。例如,如果你的activity有一個線程在後台跑下載資料從網路,它可能建立那個線程在onCreate()然後停止線程在onDestroy()。
  2、一個可視的生命期發生在onStart()和onStop()之間。在這期間,使用者可以看見activity在螢幕上並且和它互動。例如,onStop()被調時當一個新的activity開始並且這個不再被可見。在這兩個函數間,你可以維持資源那些需要用來展現activity給使用者的。例如,你可以註冊一個BroadcastReceiver在onStart(),然後登出在onStop()當使用者不再看見你顯示的東西。系統可能會調onStart(0和onStop()多次在這整個生命線期間,當activity在是否可見間轉換的時候。
  3、一個activity的前景生命期發生在onResume()和onPause()之間。在這期間,此activity在所有其它activity之上在螢幕上,並且擁有使用者焦點。一個activity可以經常轉換進和轉換出前景--例如,onPause被調用當裝置準備休眠蔌當一個對話方塊產生。因為這種狀態可以經常轉換,代碼在這兩個狀態應該輕量為了避免減慢轉換速度使得使用者等待。

  映像1陳述這些迴圈並且展現一個activity可以發生的狀態轉換路徑。矩形代表你能實現的回呼函數。

  Figure 1. The activity lifecycle.

  同樣的生命週期回呼函數被列在table 1,更加詳細的描述了回呼函數放置每一個在activity的事個生命週期,包含是否系統能殺死activity在回呼函數完成後。
  
  Table 1. A summary of the activity lifecycle's callback methods.

 

  因為onPause()他們三個中的第一個,一量activity被建立,onPause()是最後一個被保證調用的方法--如果系統必須恢複記憶體在緊急狀態,然後onStop()和onDestroy()可能將不被調用。因此,你應該使用onPause()來寫資料(例如edit)的儲存。可是,你應該精心挑選哪個資訊一定要在onPause()中留住,因為任何何阻塞的操作在這個函數阻塞到下一個activity的轉換因而降低使用者體驗。

Saving activity state
  
  本文簡單的提到了什麼一個activity被paused和stopped,activity的狀態維持著。這是真的因為activity對象仍然在記憶體當它被paused或stopped--所有的資訊關於它的成員變數和目前狀態都存在。如此,任何使用者的變化在activity中都維持在記憶體裡,所以當activity返回到前景的時候(resumes),這些變化仍然存在。
  可是,當系統摧毀一個activity為了恢複記憶體,activity對象被摧毀了,所以系統不能簡單的以完整狀態resume它。代替的是,系統必須建立Activity對象如果使用者瀏覽回它。也就是,使用者不知道系統摧毀了activity並且再建立了它,如此,可以希望activity是它剛才的那個。在這種情況下,你可以確定重要的資訊關於activity的狀態被保留通過實現一個額外的回呼函數,允許你儲存資訊關於你的activity,然後恢複它當系統重新建立它的時候。
  這個你可以儲存目前狀態資訊的回呼函數是onSaveInstanceState()。系統調這個函數在摧毀activity這前,並且傳遞一個Bundle對象。Bundle就是你可存在狀態資訊的地方,採用name-value對,使用方法如putString()。然後,如果系統殺死你的activity進程並且使用者瀏覽回到你的activity,系統傳遞Bundle給onCreate,這樣你就可以恢複activity狀態你在onSaveInnstanceState()時候儲存的狀態。如果沒有資訊被儲存,傳遞給onCreate()的Bundle是null。
  注意:不保證onSaveInstanceState()將會被調用在你的activity被摧毀前,因為有不需要儲存的情況存在(例如當使用者離開你的activity,使用者顯示的結束)。如果這個方法被調用,它總是在onStop()前,機率性在onPause()前。

  可是,即使你不做什麼事也不實現 onSaveInstanceState(),一些activity的狀態被activity類的預設onSaveInstanceState實現恢複。特別的,預設的View的onSaveInstance()在布局方面,允許每一個視圖提供它自己的資訊來被儲存。幾乎所有 的Android架構中的widget實現這個方法合適的,這樣任何可見的變化對UI都自己儲存並且恢複當你的activity被建立的時候。例如,EditText widget儲存任何文本被使用者輸入的,並且CheckBox widget儲存是否選中還是沒選中。惟一的工作要求你的是提供一個惟一的ID(通過android:id屬性)給每一個希望儲存狀態的widget。如果一個widget沒有ID,那麼 它不儲存它的狀態。
  雖然onSaveInstanceState()的預設實現儲存非常有用的資訊關於你的activity UI你仍然會需要覆蓋它來儲存額外的資訊。例如,你或許需要儲存成員變數在activity生命期間變化的(和儲存在UI中的資料有關,但儲存這些UI值的變數卻不會被預設儲存)。
  因為預設的onSaveInstanceState()幫你 你儲存UI狀態,如果你覆蓋這些方法為了儲存額外的資訊,你應該每次調用父類的實現關於onSaveinstanState()在做工作之前。
  注意:因為onSaveInstanceState()不保證被調用,你應該用它僅用它記錄臨時狀態關於你的activity--你應該永遠不用它來儲存永久性資料。代替的是,你應該用onPause()來儲存永遠性資料(例如儲存在資料庫中的資料)當使用者離開activity。
  
  一個好的方法測試你程式儲存狀態的功能是簡單的轉換裝置以使螢幕方向改變。當螢幕方向變化,系統摧毀和重建activity為了應用可選的資源,適合新方向的。出於這個原因,你的activity恢複它的狀態當建立的時候非常重要,因為使用者通常轉換螢幕在使用應用程式的時候。

Handling configuratinon changes

  一些裝置配置能在運行時改變(例如螢幕方向,鍵盤是否可用和語言)。當這樣的變化發生時,Android重新開啟運行中的Activity(onDestroy()被調用,然後onCreate()被調用)。重啟行為被設計來輔助應用程式適應新的配置通過自動載入你的應用程式通過可選的資源,你提供的。如果你設定你的activity合適的操作這個事件,它將更有彈性對生命週期中無法預料的事件。
  最好的方法操作配置變化,例如螢幕方向變,就是簡單的預定義你應用程式的狀態使用onSaveInstanceState()和onRestoreInstanceState()(或onCreate()),就像前面討論的。

Coordinating activities

  當一個activity啟動另一個,他們都在體驗生命週期轉換。第一個activitypauses和stop(雖然,它不會stop如果他仍然可見在前景),另一個activity被建立。萬一這些activities共離資料儲存到磁碟或哪,那就讓第一個activity不退出在另一個啟動前就顯得非常重要。相當的情況是,後一個進程啟動覆蓋了前一個停止的時候。

  生周周期回調被良好的定義了,特別的當兩個activities都在同一個進程,並且其中一個啟動另一個。下面是操作順序當activity A啟動activity B:
  1、Activity A 的onPause()的方法執行。
  2、Activity B 的onCreate()、onStart()和onResume()方法執行,順序的。(B現在擁有使用者焦點)
  3、如果A不再可見,它的onStop()方法執行。
  
  這種生命期函數調用序列允許你從一個activity到另一個的資訊轉換。例如,如果你必須寫入一個資料庫,當第一個activity stop,以便讓下一個activity能讀它,那麼你應該寫入資料庫在onPause()而不是onStop()。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.