編輯:Android開發實例
Android系統以不同尋常的方式處理多個應用程序的同時運行。來自於其它不同平台的開發者或許會對這樣的運行機制感到很奇怪。而理解Android多任務的運行,對於設計出可以良好運行的應用程序,以及與Android平台的其它部分進行無縫結合都具有重要意義。這篇文章說明了Android的多任務方式設計上的成因,它對應用程序運行產生的影響,還有你可以怎樣更好地利用Android的這一特性。
設計上的考慮
手機設備有硬件工藝上的限制,還有在PC環境和web系統中未曾出現過的用戶體驗的需求。以下4個關鍵約束條件是我們在設計以及實現Android的多任務機制所遵循的:
* 我們不需要用戶在使用過應用程序後關閉它們。當涉及到與眾多其它應用保持長時間的重復、簡短的交互時,(使用完成後關閉)這樣的模式就表現欠佳了。
* 手機設備並不具備大量可供交換的空間(swap space),因而對內存的使用有相當嚴格的限制。Robert Love 有 一篇很好的文章 對這一主題進行了說明。
* 在手機設備上應用程序間的切換是極其關鍵的;我們以明顯少於1秒的時間內啟動一個新的應用程序作為目標。當用戶在較少的應用程序間切換時,比如,在觀看視頻時切換去查看新的短消息然後回到視頻,這就顯得尤為重要了。這種情況下出現一次明顯的等待將很快引起用戶的不滿。
* 作為我們“所有應用程序生而平等”的設計理念的一部分,利用系統可用的APIs 必須能足以寫出Google內置的應用程序。這就意味著後台的音樂播放,數據同步,GPS導航,和應用下載必須與提供給第三方使用的是同一套APIs。
前兩項要求引發了一場有趣的爭論。我們不想讓用戶擔心要關閉他們的應用程序,而使得看上去所有應用程序一直在持續的運行。與此同時,手機設備對內存的使用有嚴格的限制,所以當一個應用需要超出系統可提供的更多的RAM時,將會降級運行或是很快運行失敗;一台具有可交換空間的台式計算機,與此相反將會在頁交換空間時出現運行遲緩。這些競爭性的限制條件成為了Android設計上的一個關鍵因素。
應用程序何時“停止”?
對Android多任務機制一個常見的誤解就是沒有很好地區分單個進程和應用(a process and an application)。在Android中它們並不是緊密耦合的實體:相對於用戶開啟的多個應用並不一定存在唯一一個實際承載這些應用的進程;多個應用之間可以共享進程,或者一個應用可以根據需要使用多個進程;即使這個應用不處於活動運行的狀態,與這一應用程序關聯的一個(或多個)進程都會由android來維護。
你看到一個應用程序的進程“正在運行”,並不意味著這個應用正在運行或是在做其它的事情。進程的存在只能說明android在某一時刻還需要它,同時決定最好保留它以便再次用到。同樣的,你可以離開應用程序一段時間然後回到原來的地方,在這期間Android可能會因為其它原因而需要終結這一進程。
Android采取這種方式管理應用程序的一個關鍵點在於進程不會被完全關閉。當用戶離開一個應用時,它的進程在後台被保留下來,而允許它在需要的時候繼續運行(比如下載web頁面),並且在用戶返回時立即回到前台。如果一個設備擁有無限的內存,那麼Android將會維持所有這些進程,真正的讓所有應用程序任一時刻都在運行。
當然了,內存的使用是有限制的,為了作出平衡Android必須能決定在什麼時候移除它不再需要的進程。這就產生了Android的進程生命周期(process lifecycle),它以這樣的規則決定了各個進程的重要性以及下一個需要被清除的進程。這些規則是基於與當前用戶體驗所關聯進程的重要程度,以及從用戶上次使用到現在該進程經歷了多長時間來共同設定的。
一旦Android決定需要移除一個進程,它將使用蠻力簡單的強制終止該進程。系統內核就能回收該進程關聯的所有資源,而不依賴於應用是不是具有良好的實現,而發出交互的請求詢問是否退出。允許內核立即回收應用程序的資源,可以帶來極大方便以避免嚴重的內存耗盡情況的出現。
如果用戶隨後返回到已經被終止的應用,Android需要一種方式以該應用在最後可見時的狀態來重新啟動它,來實現“所有的應用在任一時刻都在運行”的用戶體驗。Android通過追蹤用戶關心的應用程序的一部分(the Activities),並且以其最後可見時的狀態信息來實現對它們的重新啟動。這一最後狀態是在每次用戶離開應用程序的這一部分時生成的,而不是在應用程序被終止時產生,所以系統內核隨後可以終止應用程序,而不需要在終結的時刻要求應用程序作出正確的交互響應。
在某種程度上來看,Android的進程管理與內存空間的置換具有相同的形式:應用進程代表了一定量的正在使用中的內存;當系統內存降低,一些進程可以被終止(換出 swapped out);當再次需要這些進程時,它們可以從上次保存的狀態重新啟動(換入 swapped in)。
顯式的後台運行
到現在為止,對應用程序我們有一種隱式的方式讓它們在後台工作,只要Android按照它常規的內存管理方式終止這些進程。這樣的方式對於在後台加載web頁面一類的應用來說是沒有問題的,但是如果有更高要求的應用特性要實現呢?象後台的音樂播放,數據同步,定位追蹤,鬧鐘等等。
對於以上的這些任務,應用程序需要有一種方式告訴Android“這時候我想要顯式的運行。” 對這類應用有兩種可以利用的機制,它們也代表著兩種可以在應用的manifest中聲明的組件:broadcast receiver 和 services。
Broadcast Receiver
BroadcastReceiver 可以讓應用程序在一段限定的時間裡,作為其它事件發生的結果而在後台運行。它可以被應用在構建高級特性的很多方面:例如AlarmManager 讓應用程序在未來的某個確定時間裡發出一個廣播,而對於LocationManager當它檢測到位置發生變化時就可以發送出一個廣播。因為與receiver有關的信息是應用程序manifest中的一部分,Android可以發現以及啟動應用程序即使它不是正處於運行狀態;當然了,如果它在後台已經有了對應可用的進程,那麼廣播就能被高效地分發給它。
應用程序設定了固定的時間(現在是10秒)來完成對一個廣播的處理。如果它在這段時間沒有執行完成,那麼這個應用程序就會被認為行為異常,它的進程會被馬上被置為後台運行狀態,在系統需要時回收內存而被終結。
BroadcastReceiver 非常適合於響應外部的行為來做少量的工作,如在收到一個新的GPS位置消息後給用戶發布一個通告。由於應用的進程在主動接受廣播時僅僅需要在場,它們具有非常輕量級的特征。又因為它們只能在確定性的時間裡活動,所以在運行時就可以有很好的保證讓它們的進程不被終止。
Services
Service 讓應用程序可以實現後台操作的持續運行。實際上各類服務提供的包含有很多功能,但是基於當前的討論來說它們的基本目的就是讓一個應用程序跟系統說“嘿,我想在後台能夠持續的運行,直到我說已經完成了。” 應用程序對運行在其中的服務擁有顯示啟動和停止的控制權。
Service提供了一種富客戶機-服務器 模式,而它的使用方式是可選的。在啟動了一個應用的服務後,緊接著Android簡單實例化了在應用進程中的組件為其提供context。在這之後服務被怎樣使用是由應用程序來決定的:它可以把所需的所有代碼放到服務自身中而不與應用程序中的其它部分進行交互,調用與應用程序的其它部分共享的單例對象,如果需要從其他部分直接得到服務的實例,或是根據需要把服務放到另一個進程中用作完全的RPC調用。
針對service 的進程管理與對broadcast receivers 的進程管理是不同的,因為一系列未被綁定的服務可能被要求運行不確定的時間。可能不會有足夠的RAM來讓所有請求的服務都得到運行,所以沒有強力的保證可以讓他們都運行。
在RAM空間不足時,有服務寄宿的進程就會像後台進程一樣被立即終結掉。然而,當條件合適的時候,Android將記得那些想要保持運行的服務,並且隨後在有更多RAM空間可用時重啟這些進程。例如,如果用戶進入到一個需要大量RAM空間的web頁面時,Android可能會同步終止其後台服務進程直到浏覽器的內存需求量下降。
Service可以通過請求將他們當成“前台”而進一步與系統協商其行為。結果就會使服務處於“請不要終結”(please don't kill)的狀態,但是也要求它包含一個對用戶的通告(notification)以說明它的活動運行。這對於用戶主動關注的服務,如後台音樂播放或車載導航是很有用處的;當播放音樂和使用浏覽器時,你總可以看見狀態欄中音樂播放的圖標。Android不會嘗試去終止這些服務,但是作為一個折中的方案,你需要確保用戶知道並可以在需要的時候顯示地停止它們。
通用組件的價值
Android的通用broadcast receiver 和 service 組件使開發者可以打造廣泛高效的後台操作,其中包括了很多最初並未考慮到的操作。在Android1.0中,它們被用來實現系統內建的以及屬於Google應用專利所提供的幾乎所有的後台行為:
* 音樂播放在一個服務中運行,在用戶離開該音樂應用程序時仍可以持續運轉。
* 鬧鐘應用程序調度一個與alarm manager關聯的broadcast receiver,使其在下一次設置的時間點響鈴。
* 日歷應用程序同樣的為下一個日歷事件調度了一個alarm 以便在合適的時候顯示或更新它的通告。
* 當有任何下載任務需要處理時,後台文件下載以服務的形式實現。
* e-mail應用程序設置了一個alarm使其在規定的時間間隔內喚醒服務去查收任何到來的新的郵件。
* Google應用程序自身維護了一個服務來接受來自網絡推送來的通告消息;當它被告知有應用想完成象同步聯系人這樣的事情時,對應的就會發送廣播給單個的應用。
隨著Android平台的進化,也有一些基礎的組件已經用來實現很多主要的與開發者有關的新特性:
* 輸入法已經由開發者作為一個服務組件進行了實現,Android應用和管理它,目前作為IME來顯示。
* Application widgets 是broadcast receivers,在Android想要與之交互時就會發送廣播給它們。這就使得app widgets 變成輕量級的,也就不需要它們關聯應用的進程保持運行狀態。
* 可訪問性的功能是作為服務實現的,在使用時Android保持其運行態並就用戶的交互發送對應的信息給它。
* 在Android2.0 中引入的同步適配器(Sync adapters)當有特定的數據同步需要被執行時,它作為服務運行於後台。
* 活動壁紙也是一種服務,在用戶選擇壁紙後由Android開啟服務。
欣賞一下我們清爽的界面吧~ 如果是只用activity來制作這樣的東西簡直是太小兒科了,此處我們當然用的是service 首先我們先上service的代碼: 1
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
Android提供了許多方法來控制播放的音頻/視頻文件和流。其中該方法是通過一類稱為MediaPlayer。Android是提供MediaPlayer類訪問內置的媒體播放
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩