Binder學習(一)Android中的程式

wustor發表於2017-11-23

概述

我麼知道,Android底層是基於Linux核心的,當某個應用元件啟動且該應用沒有執行其他任何元件時,Android 系統會使用單個執行執行緒為應用啟動新的 Linux 程式。預設情況下,同一應用的所有元件在相同的程式和執行緒(稱為主執行緒)中執行。對於執行緒,基本上大家都比較熟悉,因為主執行緒中不允許有耗時的操作,基本上會根據需要開一些子執行緒來處理一些耗時的操作,諸如IO,網路之類的,然後最好用執行緒池統一進行管理。但是對於程式來說,其實比執行緒要複雜的多,有時候想一下,其實有很多問題是值得研究的:

  • 為什麼每個應用都可以接收到系統的廣播?
  • 為什麼不同的應用之間可以相互喚起?
  • 為什麼不同的應用都可以訪問系統相簿,通訊錄?

自己不是做底層的,也不打算去研究底層的原始碼,只打算從應用層上了解一下Android系統應用間的通訊機制。

正文

四大元件的程式

預設情況下,同一應用的所有元件均在相同的程式中執行,且大多數應用都不會改變這一點。 但是,如果您發現需要控制某個元件所屬的程式,則可在清單檔案中執行此操作。

開啟多程式

對於一個Application來講,系統會預設分配一個程式,但是這個屬性可以在清單檔案中通過android:process屬性進行配置,另外這個屬性同樣適用於activity、service、receiver和 provider,下面舉例說明:

   <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:process="application process"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:process="activity process">
            </intent-filter>
        </activity>
    </application>複製程式碼

程式的分類

前臺程式

使用者當前操作所必需的程式。如果一個程式滿足以下任一條件,即視為前臺程式:

  • 託管使用者正在互動的 Activity(已呼叫 Activity 的 onResume() 方法)
  • 託管某個 Service,後者繫結到使用者正在互動的 Activity
  • 託管正在“前臺”執行的 Service(服務已呼叫 startForeground())
  • 託管正執行一個生命週期回撥的 Service(onCreate()、onStart() 或 onDestroy())
  • 託管正執行其 onReceive() 方法的 BroadcastReceiver
可見程式

沒有任何前臺元件、但仍會影響使用者在螢幕上所見內容的程式。 如果一個程式滿足以下任一條件,即視為可見程式:

  • 託管繫結到可見(或前臺)Activity 的 Service。
  • 託管不在前臺、但仍對使用者可見的 Activity(已呼叫其 onPause() 方法)。例如,如果前臺 Activity 啟動了一個對話方塊,允許在其後顯示上一 Activity,則有可能會發生這種情況。
服務程式

正在執行已使用 startService() 方法啟動的服務且不屬於上述兩個更高類別程式的程式。儘管服務程式與使用者所見內容沒有直接關聯,但是它們通常在執行一些使用者關心的操作(例如,在後臺播放音樂或從網路下載資料)。

後臺程式

包含目前對使用者不可見的 Activity 的程式(已呼叫 Activity 的 onStop() 方法)。 通常會有很多後臺程式在執行,因此它們會儲存在 LRU (最近最少使用)列表中,以確保包含使用者最近檢視的 Activity 的程式最後一個被終止。如果某個 Activity 正確實現了生命週期方法,並儲存了其當前狀態,則終止其程式不會對使用者體驗產生明顯影響,因為當使用者導航回該 Activity 時,Activity 會恢復其所有可見狀態。 有關儲存和恢復狀態的資訊。

空程式

不含任何活動應用元件的程式。保留這種程式的的唯一目的是用作快取,以縮短下次在其中執行元件所需的啟動時間。

程式生命週期

Android 系統將盡量長時間地保持應用程式,但為了新建程式或執行更重要的程式,最終需要移除舊程式來回收記憶體。 為了確定保留或終止哪些程式,系統會根據程式中正在執行的元件以及這些元件的狀態,將每個程式放入“重要性層次結構”中。 必要時,系統會首先消除重要性最低的程式,然後是重要性略遜的程式,依此類推,以回收系統資源。

  • 前臺程式:通常,在任意給定時間前臺程式都為數不多。只有在記憶體不足以支援它們同時繼續執行這一萬不得已的情況下,系統才會終止它們。 此時,裝置往往已達到記憶體分頁狀態,因此需要終止一些前臺程式來確保使用者介面正常響應。
  • 可見程式:可見程式被視為是極其重要的程式,除非為了維持所有前臺程式同時執行而必須終止,否則系統不會終止這些程式。
  • 服務程式:除非記憶體不足以維持所有前臺程式和可見程式同時執行,否則系統會讓服務程式保持執行狀態。
  • 後臺程式:這些程式對使用者體驗沒有直接影響,系統可能隨時終止它們,以回收記憶體供前臺程式、可見程式或服務程式使用
  • 空程式:為使總體系統資源在程式快取和底層核心快取之間保持平衡,系統往往會終止這些程式。

提高程式優先順序

根據程式中當前活動元件的重要程度,Android 會將程式評定為它可能達到的最高階別。例如,如果某程式託管著服務和可見 Activity,則會將此程式評定為可見程式,而不是服務程式。

此外,一個程式的級別可能會因其他程式對它的依賴而有所提高,即服務於另一程式的程式其級別永遠不會低於其所服務的程式。 例如,如果程式 A 中的內容提供程式為程式 B 中的客戶端提供服務,或者如果程式 A 中的服務繫結到程式 B 中的元件,則程式 A 始終被視為至少與程式 B 同樣重要。

由於執行服務的程式其級別高於託管後臺 Activity 的程式,因此啟動長時間執行操作的 Activity 最好為該操作啟動服務,而不是簡單地建立工作執行緒,當操作有可能比 Activity 更加持久時尤要如此。例如,正在將圖片上傳到網站的 Activity 應該啟動服務來執行上傳,這樣一來,即使使用者退出 Activity,仍可在後臺繼續執行上傳操作。使用服務可以保證,無論 Activity 發生什麼情況,該操作至少具備“服務程式”優先順序。 同理,廣播接收器也應使用服務,而不是簡單地將耗時冗長的操作放入執行緒中。

針對上述原理,所以常用的提升程式優先順序的方法大致有以下2種:

設定程式優先順序

對於Service被系統回收,一般做法是通過提高優先順序可以解決,有以下幾種做法:

  • 在AndroidManifest.xml檔案中對於intent-filter可以通過android:priority = “1000”這個屬性設定最高優先順序,1000是最高值,如果數字越小則優先順序越低。

  • Android中的程式是託管的,當系統程式空間緊張的時候,會依照優先順序自動進行程式的回收, 設定setForeground(true) 來設定 Service 的優先順序。

雙程式守護

APP中同時開啟兩個Service,分別是A和B,那麼: 如果A守護B,則B掛掉的同時,A就應該把B啟動起來,反之亦然,也就是說A和B應該是互相守護,無論誰被殺掉,對方就把它拉起來。

相關文章