Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android應用程序模型之應用程序,任務,進程,線程分析

Android應用程序模型之應用程序,任務,進程,線程分析

編輯:關於Android編程

本文講述了Android應用程序模型之應用程序,任務,進程,線程。分享給大家供大家參考,具體如下:

大多數操作系統,在應用程序所寄存的可執行程序映像(如Windows系統裡的.exe)、它所運行的進程以及和用戶交互的圖標和應用之間有一種嚴格的1對1關系。在Android系統裡,這些關聯要松散得多。並且重要的是要理解各種概念怎麼樣組成整體。

由於Android應用固有的靈活性,當實現這些不同方面的時候有一些基本術語需要加以理解:

① 一個Android包 (.apk)文件,其中包含一個應用程序的代碼和資源。這是應用程序分發和下載的文件,用戶用來安裝該應用程序在他們的設備上。
② 一個任務一般而言是指用戶視為的一個可啟動應用程序:通常任務在桌面(home screen)有一個可訪問的圖標,且可以被切換到前台。
③ 一個進程是一個運行著應用程序代碼的底層核心過程。通常所有.apk裡的代碼運行在一個專有的進程裡。不過,進程標記也可以用來限定代碼運行位置,或者為整個.apk或者為個別的活動activity,接收者receiver,服務或提供者provider,組件。

任務

這裡的一個關鍵點是:當用戶看到一個“應用”時,他們實際上在和任務打交道。如果您剛剛創建一個包含若干活動的.apk,其中之一是頂層入口點(通過動作android.intent.action.MAIN的意圖過濾器intent-filter和類別android.intent.category.LAUNCHER),那麼這事實上將為您的.apk創建一個任務,並且您從那兒起動的任何活動都將作為那個任務的一部分運行。

一個任務,那麼,從用戶的角度來看是您的應用程序;而從應用程序開發者的角度來看,它是一個或多個用戶在那個任務中已經經歷過且未關閉的活動,或者說是一個活動棧。一個新的任務通過以Intent.FLAG_ACTIVITY_NEW_TASK標志起動一個活動意圖來創建;這一意圖將被用來作為任務的根意圖,定義任務是什麼。任何不以這個標志起動的活動將和起動它的活動在相同的任務中運行(除非該活動已請求特別啟動模式,稍後會討論)。任務可以被重新安排:如果您使用FLAG_ACTIVITY_NEW_TASK標志但已經有一個任務以這個意圖運行,則當前任務的活動棧將被切換到前台而不是開始一個新的任務。

FLAG_ACTIVITY_NEW_TASK必 須謹慎使用:使用它意味著,在用戶看來,一個新的應用程序由此起動。如果這不是你所期望的行為,你就不該去創建一個新的任務。另外,僅在用戶可以從桌面返 回到他原來的地方和以一個新任務啟動相同意圖的情況下,你才應該使用新的任務標記。否則,如果用戶在你已經啟動的任務裡按桌面(HOME)鍵,而不是返回(BACK)鍵,你的任務及其活動將被放置到桌面後面,沒有辦法再切換回去。

任務共用性Affinity

在某些情況下,Android需要知道一個活動屬於哪個任務即使它沒有被啟動到一個具體的任務裡。這是通過任務共用性(Affinities)完成的。任務共用性(Affinities)為這個運行一個或多個活動的任務提供了一個獨特的靜態名稱,默認的一個活動的任務共用性(Affinity)是實現了該活動的.apk包的名字。這提供了預期的標准特性,即所有在一個特定的.apk包裡的活動是單個用戶應用程序的一部分。

當開始一個沒有Intent.FLAG_ACTIVITY_NEW_TASK標志的活動時,任務共用性affinities不會影響將會運行該新活動的任務:它總是運行在啟動它的任務裡。但是,如果使用了NEW_TASK標志,那麼共用性(affinity)將被用來判斷是否已經存在一個有相同共用性(affinity)的任務。如果是這樣,這項任務將被切換到前面而新的活動會啟動於這個任務的頂層。

這種特性在您必須使用NEW_TASK標志的情況下最有用,尤其是從狀態欄通知或桌面快捷方式啟動活動時。結果是,當用戶用這種方式啟動您的應用程序時,它的當前任務將被切換到前台,而且想要查看的活動被放在最上面。

你可以在程序清單(Manifest)文件的應用程序application標簽中為.apk包中所有的活動分配你自己的任務共用性Affinites,或者在活動標記中為各個活動進行分配。一些說明其如何使用的例子如下:

① 如果您的.apk包含多個用戶可以啟動的高層應用程序,那麼您可能需要對用戶看到的每個活動指定不同的affinities。一個不錯的命名慣例是以附加一個以冒號分隔的字符串來擴展您的.apk包名。例如,“ com.android.contacts ”.apk可以有affinities:“com.android.contacts:Dialer”和“ com.android.contacts:ContactsList”。
② 如果您正在替換一個通知,快捷方式,或其他可以從外部發起的應用程序的“內部”活動,你可能需要明確設定您替代活動的taskAffinity和您准備替代的應用程序一樣。例如,如果您想替換contacts詳細信息視圖(用戶可以創建並調用快捷方式),你得把taskAffinity設置成“com.android.contacts”。

啟動模式和啟動標志

您控制活動和任務交互的主要途徑是通過活動的launchMode 屬性和意圖相關的標志flags。這兩個參數可以以各種方式合作來控制活動啟動的結果,正如它們相關文檔中描述的那樣。在這裡,我們將看看一些常見的用例和參數組合。

你將使用的最常見的啟動模式(除了默認的standard模式)是singleTop。這並不影響任務;它只是避免多次在一個堆棧頂部起動同一活動。

singleTask啟動模式對任務有重大的影響:它使活動始終是開始於一項新的任務(或其現有的任務被帶到前台) 。使用這種模式需要謹慎對待你如何與系統其他部分進行交互,因為這影響到這個活動中的每一個路徑。它應當僅在活動處於應用程序前台時使用(也就是支持MAIN動作和LAUNCHER類別)。

singleInstance啟動模式更是專業,並應僅用於整個就是被實現為一個活動的應用程序中。

有一種你會經常遇到的情況是當另一個實體(如SearchManager 或NotificationManager)開始您的一個活動。在這種情況下,必須使用Intent.FLAG_ACTIVITY_NEW_TASK 標簽,因為該項活動是在任務之外起動的(而且應用/任務可能根本不存在)。正如前面所述,這種情況下的標准行為是把匹配新活動affinity的任務帶到前台和在此之上起動新的活動。不過,也有其他您可以實施的行為類型。

一種通常的辦法是和NEW_TASK聯合起來使用Intent.FLAG_ACTIVITY_CLEAR_TOP標志。這樣,如果您的任務已經運行,那麼它將會被帶到前台,除根活動外其它所有堆棧中的活動都被清除,而且這個根活動的方法onNewIntent(Intent)會在該意圖起動時被調用。注意這個活動使用這個方法時經常使用singleTop或者singleTask起動模式,這樣當前實例被賦予新的意圖而不是需要銷毀它然後重新起動一個新的實例。

您能采取的另外的方法是設置通知活動的任務affinity為空字符串“”(表示沒有affinity),並設置finishOnBackground屬性。這種方法是有用的如果你希望這個通知把用戶帶到一個單獨的描述它的活動中,而不是返回到應用程序的任務。通過指定這個屬性,該活動將被結束不管用戶通過BACK還是HOME離開它;如果這個屬性沒有指定,按首頁將導致這個活動及其任務仍保留在系統裡,且可能沒有辦法返回它。

請務必閱讀關於launchMode屬性和Intent標志的文檔以獲取這些選項的詳細說明。

進程

在Android裡,進程完全是應用的實現細節,而不是用戶通常了解的那樣。其主要用途就是:

① 通過安置不受信任的或不穩定的代碼到另一個進程來提高穩定性或安全性。
② 通過在同一進程裡運行多個.apks的代碼來減少開銷。
③ 通過把重量級代碼放在單獨的進程中來幫助系統管理資源,該進程可以在不影響應用程序其他部分的情況下被終止。

正如前面所述,這個進程屬性用來控制運行著特定應用程序組件的進程,注意,此屬性不能用於違反系統安全性:如果有兩個不共享相同用戶ID的.apks嘗試運行在同一進程中,這將不會被允許,相反會為它們每一個創建不同的進程。

參見安全文檔以獲取更多關於安全限制方面的信息。

線程

每個進程包含一個或多個線程。多數情況下,Android避免在進程裡創建額外的線程,以保持應用程序單線程,除非它創建自己的線程。一個重要的結果就是所有對活動Activity,廣播接收器BroadcastReceiver以及服務Service實例的調用都是由這個進程的主線程創建的。

注意新的線程並不會為每個活動,廣播接收器,服務或者內容提供器(ContentProvider) 實例而創建:這些應用程序的組件在進程裡被實例化(除非另有說明,都在同一個進程處理),實際上是進程的主線程。這說明當被系統調用時沒有哪個組件(包括 服務)會進行遠程或者阻塞操作(就像網絡調用或者計算循環),因為這將阻止進程中的所有其他組件。你可以使用標准的線程類Thread或者Android的HandlerThread便捷類去對其它線程執行遠程操作。

這裡有一些關於這個線程規則的重要的例外:

① 對IBinder或者IBinder實現的接口的調用由調用線程或本地進程的線程池(如果該呼叫來自其他進程)分發,而不是它們的進程的主線程。特殊情況下,一個服務的IBinder可以這樣調用。(盡管調用服務裡的方法已經在主線程裡完成。)這意味著IBinder接口的實現必須要有一種線程安全的方法,這樣任意線程才能同時訪問它。
② 對ContentProvider主要方法的調用由調用線程或者主線程分發,如同IBinder一樣。被指定的方法在內容提供器的類裡有記錄。這意味著實現這些方法必須要有一種線程安全的模式,這樣任意其它線程可以同時訪問它。
③ 視圖及其子類中的調用由正在運行著視圖的線程產生。通常情況下,這會被作為進程的主線程,如果你創建一個線程並顯示一個窗口,那麼繼承的窗口視圖將從那個線程裡啟動。

希望本文所述對大家Android程序設計有所幫助。

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