<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ### **概述** Android應用開發的哲學是把一切都看作是組件。把應用程序組件化的好處是降低模塊間的耦合性,同時提高模塊的復用性。Android的組件設計思想與傳統的組件設計思想最大的區別在于,前者不依賴于進程。也就是說,進程即使由于內存緊張被強行殺掉了,但是運行在里面的組件還是存在的。這樣就可以在組件再次需要使用時,原地滿血復活,就像什么都沒發生過一樣。這種設計思想非常適合內存較小的移動設備。 理解Android組件設計思想,對Android應用程序架構會有更好的認識。這一節講Android組件化設計的背景、理念、原則,以及Android在OS級別上提供的組件化支持,其中還會包含一個實驗來驗證這種組件化設計思想,可以對Android系統有一個高層次的抽象理解。 * 組件化背景 * 組件化設計 * 組件化支持 * 一個小實驗 ### **組件化背景** #### **從PC客戶端應用程序說起** * 開發者角度 * 復雜,同時兼顧UI、交互和業務邏輯 * 運行載體是進程 * 進程只有一個入口點—main * 使用者角度 * 流暢的UI、友好的交互、正確的結果 * 不知進程是何物 #### **PC客戶端應用程序開發的任務** * 滿足用戶的需求 * 降低程序復雜度 -- 組件化 #### PC客戶端應用程序組件化之后 * 開發者角度 * 運行載體仍然是進程 * 進程仍然是只有一個入口點—main * 使用者角度 * 流暢的UI、友好的交互、正確的結果 * 不知進程是何物 #### **結論** 應用程序組件化前后,用戶對其運行載體(進程)沒有概念,但是開發者來說,組件化后的應用程序仍然是和進程直接關聯的,也就是說,進程一旦不存在,程序和組件也隨之灰飛煙滅! #### **再說移動客戶端應用程序** * 與PC客戶端應用程序一樣,包含UI、交互和業務等復雜邏輯 * 與PC客戶端應用程序一樣,用戶的需求是流暢的UI、友好的交互、正確的結果 * 運行在低頻率CPU、小容量內存、小面積屏幕設備上 #### **設備特性對移動客戶端應用程序的影響** * 低頻率CPU 影響程序運行速度,尤其是程序啟動速度,因為用戶對程序啟動時間最為敏感 * 小容量內存 影響同時運行的程序的數量,而且系統會在內存緊張時殺進程,以便回收內存 * 小面積屏幕 單窗口操作模式,導致用戶需要頻繁地切換程序或者重新打開程序 #### **移動客戶端應用程序開發的任務** * 滿足用戶的需求 * 降低程序復雜度 #### **組件化是降低移動端應用程序復雜度的不二選擇,但需進一步考慮以下兩個事實**: * 設備特性的影響 * 系統殺進程時,被殺進程里面的組件如何處理? * 程序切換和重新打開時,如可提高程序啟動速度? * 用戶不關心進程 * 是否可以將組件與進程進行剝離? ### **組件化設計** #### **基本思想** Everything is component #### **具體實現** * 程序由組件組成 * 組件與進程剝離 * 組件皆程序入口 #### **程序由組件組成** * Activity:前臺交互 * Service:后臺計算 * Broadcast Receiver:廣播通信 * Content Provider:數據封裝 此四種組件對客戶端應用程序進行了很好的抽象,QT的signal-slot,COM的連接點,都是廣播的例子 #### **組件與進程剝離** * 組件關閉時,進程可以繼續存在 提高重新啟動時的速度 * 進程關閉時,組件可以繼續存在 保護被殺進程里面的組件 #### **組件皆程序入口** * Activity -- onCreate * Service -- onCreate * Broadcast Receiver -- onReceive * Content Provider -- onCreate 由于組件已與進程剝離,因此不再有進程入口的概念,只有組件入口的概念 #### **將組件與進程進行剝離,使得進程對組件透明,聽起來很好,但是如何解決以下四個問題?** * 誰來負責組件的啟動和關閉? * 誰來維護組件的狀態? * 誰來管理組件運行時所需要的進程? * 組件之間如何進行通信? ### **組件化支持** #### **操作系統級別的組件化支持** * Activity Manager Service * Binder * Low Memory Killer #### **Activity Manager Service** * 啟動組件 組件啟動時,檢查其所要運行在的進程是否已創建。如果已經創建,就直接通知它加載組件。否則,先將該進程創建起來,再通知它加載組件。 * 關閉組件 組件關閉時,其所運行在的進程無需關閉,這樣就可以讓組件重新打開時得到快速啟動。 * 維護組件狀態 維護組件在運行過程的狀態,這樣組件就可以在其所運行在的進程被回收的情況下仍然繼續生存。 * 進程管理 在適當的時候主動回收空進程和后臺進程,以及通知進程自己進行內存回收 1. 組件的UID和Process Name唯一決定了其所要運行在的進程。 2. 每次組件onStop時,都會將自己的狀態傳遞給AMS維護。 3. AMS在以下四種情況下會調用trimApplications來主動回收進程: A. activityStopped B. setProcessLimit C. unregisterReceiver D. finishReceiver 4. WMS也會主動回收進程: WindowManagerService在處理窗口的過程中發生Out Of Memroy時,會調用reclaimSomeSurfaceMemoryLocked來回收某些Surface占用的內存,reclaimSomeSurfaceMemoryLocked的邏輯如下所示: (1).首先檢查有沒有泄漏的Surface,即那些Session已經不存在但是還沒有銷毀的Surface,以及那些宿主Activity已經不可見但是還沒有銷毀的Surface。如果存在的話,就將它們銷毀即可,不用KillPids。 (2).如果不存在沒有泄漏的Surface,那么那些存在Surface的進程都有可能被殺掉,這是通過KillPids來實現的。 **KillPids**: * (1). 找中候選進程的最大oom_adj值。 * (2). 如果找到的最大oom_adj值恰好位于[ProcessList.HIDDEN_APP_MIN_ADJ(9), ProcessList.HIDDEN_APP_MAX_ADJ(15)]之間,那么就將最大oom_adj值修改為ProcessList.HIDDEN_APP_MIN_ADJ,表示要將所有后臺進程都殺掉。 * (3). 如果此時殺進程是不安全的,并且找到的最大oom_adj值比ProcessList.SERVICE_ADJ還要小,那么就將將最大oom_adj值設置為ProcessList.SERVICE_ADJ,避免重要進程被殺掉。 * (4). oom_adj值大于等于前面找到的最大oom_adj值的候選進程都將被殺掉。 **trimApplications**: * (1). 殺掉Package已經被Remove了的進程,屬于無用進程 * (2). 調用updateOomAdjLocked更新所有進程的oom_adj **updateOomAdjLocked -- all**: * (1). 根據進程運行狀態來更新進程的oom_adj。更新順序是從最近使用到最近不使用的。如果一個進程是后臺進程,那么按照這個順序進行更新,就意味著最近越是不使用的后臺進程,它獲得的oom_adj值就越大。后臺進程(以及空進程)的oom_adj取值范圍[ProcessList.HIDDEN_APP_MIN_ADJ(9), ProcessList.HIDDEN_APP_MAX_ADJ(15)] * (2),如果空進程超過限制,那么最近越是不使用的空進程,就越會被殺掉。 * (3). 如果后臺進程超過限制,那么最近越是不使用的后臺進程,就越會被殺掉。 * (4). 通知進程ScheduleTrimMemory。 updateOomAdjLocked -- single: * (1). 調用computeOomAdjLocked計算oom_adj。 * (2). 計算oom_adj之后,如果ShchedGroup發生改變,并且變成了THREAD_GROUP_BG_NONINTERACTIVE調度組,那么進程就會被殺掉。 **computeOomAdjLocked**: * (1). ProcessList.FOREGROUND_APP_ADJ(0): 前臺進程、有InstrumentionClass的進程、正在接收廣播的進程、正在執行Service Callback的進程、正在運行有外部依賴的Content Provider的進程 * (2). ProcessList.VISIBLE_APP_ADJ(1): 有Activity是Visible的進程 * (3). ProcessList.PERCEPTIBLE_APP_ADJ(2):有Activity是Pausing、Paused或者Stopping狀態的進程、有Service被設置為Foreground的進程、被設置為Foreground的進程。 * (4). ProcessList.HEAVY_WEIGHT_APP_ADJ(3):被設置為重量級App的進程。 * (5). ProcessList.BACKUP_ADJ(4):正在執行備份任務的進程。 * (6). ProcessList.SERVICE_ADJ(5):最近有活動的Service的進程。 * (7). ProcessList.HOME_APP_ADJ(6):Home App進程。 * (8). ProcessList.PREVIOUS_APP_ADJ(7):前一個顯示UI的進程。 * (9). ProcessList.SERVICE_B_ADJ(8):oom_adj值等于ProcessList.SERVICE_ADJ的進程超過限制時,最近越是不使用的進程的oom_adj值就會由ProcessList.SERVICE_ADJ變成ProcessList.SERVICE_B_ADJ。 **PS**: * (1). 如果一個進程運行有綁定至另外一個進程(Client)的Content Provider或者Service,并且client進程的oom_adj值比該進程的oom_adj小,那么該進程的oom_adj值就會被設置為client進程的oom_adj值,但是不能超過ProcessList.FOREGROUND_APP_ADJ。 * (2). ProcessList.PERSISTENT_PROC_ADJ(-12):被設置為persistent的進程,如PhoneApp,不參與oom_adj更新計算。 * (3). ProcessList.SYSTEM_ADJ(-16):System進程,不參與oom_adj更新計算。 #### **Binder** * 為組件間通信提供支持 * 進程間 * 進程內 * 高效的IPC機制 * 進程間的組件通信時,通信數據只需一次拷貝 * 進程內的組件通信時,跳過IPC進行直接的通信 傳統的IPC,通信數據需要執行兩次,一次是從源進程的用戶空間拷貝到內核空間,二次是從內核空間拷貝到目標進程的用戶空間 ### **Low Memory Killer** * 內存緊張時回收進程 由于組件與進程是剝離的,因此進程回收不會影響組件的生命周期 * 從低優先級進程開始回收 * Empty Process * Hidden Process * Perceptible Process * Visible Process * Foreground Process **備注:** 1. 每一個APP進程都有一個oom_adj值,該值是根據進程所運行的組件計算出來的,值越小,優先級就越級。 2. Init和System Server進程的oom_adj等于-16,是最高的,保證不會被殺死。 3. PhoneApp具有persist屬性,它的oom_adj被設置為-12,也能保證不會被殺死。 4. 可以通過`/proc/<pid>oom_adj`文件查看進程的oom_adj值。 5. 在Linux內核中,子進程的oom_adj值等于父進程的oom_adj,也就是說,Android里面的Native進程的oom_adj值與fork它的進程的oom_adj值一樣。 ### **一個小實驗** ![](https://box.kancloud.cn/6b0a21741ce83aee9bb14f9e02eaec5b_730x427.jpg) ![](https://box.kancloud.cn/11d7df7d87dfe78872979ca93ee81c0c_376x535.jpg) ![](https://box.kancloud.cn/2a6bb88d43b77719b55c64f1a74e2dc8_558x498.jpg) ![](https://box.kancloud.cn/9312ef0cf2b9ba90789c4702ff961435_648x379.jpg) ![](https://box.kancloud.cn/c77136efc5ba8eaf15202a9f46692f2b_557x510.jpg) ![](https://box.kancloud.cn/c965bf242f8563dee2137547d511bf9a_376x535.jpg) ![](https://box.kancloud.cn/a27568f6388372fe758ad74adf42cfed_561x487.jpg) #### **參考** [Google安卓開發培訓入門指南](http://developer.android.com/training/index.html) [Google安卓開發應用組件](http://developer.android.com/guide/components/index.html) [Android 源代碼](http://source.android.com/source/index.html) [Android 接口和架構](http://source.android.com/devices/index.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看