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

Android開發之Activity詳解

編輯:關於Android編程

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>元素的子元素。例如:

https://www.android5.online/Android/UploadFiles_5356/201603/2016031512574772.png

Using intent filters

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

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

https://www.android5.online/Android/UploadFiles_5356/201603/2016031512574709.png

  <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:

https://www.android5.online/Android/UploadFiles_5356/201603/2016031512574753.png

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

https://www.android5.online/Android/UploadFiles_5356/201603/2016031512574774.png

  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和操作結果:

https://www.android5.online/Android/UploadFiles_5356/201603/2016031512574820.png

  這個例子展現了基本的邏輯你應該使用的在你的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骨架包含每一個基本的生命周期函數:

https://www.android5.online/Android/UploadFiles_5356/201603/2016031512574837.png

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

  放在一起,這些函數定義了整個生命周期關於一個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可以發生的狀態轉換路徑。矩形代表你能實現的回調函數。

https://www.android5.online/Android/UploadFiles_5356/201603/2016031512574818.png

  Figure 1. The activity lifecycle.

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

https://www.android5.online/Android/UploadFiles_5356/201603/2016031512574874.png 

  因為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恢復它的狀態當創建的時候非常重要,因為用戶通常轉換屏幕在使用應用程序的時候。

https://www.android5.online/Android/UploadFiles_5356/201603/2016031512574830.png

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()。

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