Android系統流程

Zygote的啓動過程

1.系統啓動init進程時會啓動Zygote進程(負責Android運行時進程和應用進程的啓動)
2.Zygote進程會首先啓動SystemServer進程,SystemServer進程會啓動系統的關鍵服務(PMS和AMS)
3.當啓動應用程序時,AMS經過socket向Zygote通知建立新的進程
canvas

Android應用程序安裝過程

  • 系統啓動安裝過程
  1. SystemServer進程啓動PackageManagerService服務實例,添加到ServiceManager(負責管理系統中的Binder對象)
    bash

  2. PackageManagerService.main()掃描指定目錄的apk歸檔文件
    app

/system/framework
/system/app
/vendor/app
/data/app
/data/app-private
複製代碼
  1. 對apk文件解析AndroidManifest.xml各個標籤,獲得的package、provider、service、receiver和activity等信息保存在PackageManagerService服務的內存中。
  • 下載安裝過程 下載apk->拷貝到指定目錄->解析apk歸檔文件的AndroidManifest.xml的應用程序的信息到packageManagerServices中 #應用程序啓動流程
  1. Launcher經過Binder進程間通訊機制通知ActivityManagerService,它要啓動一個Activity;
  2. ActivityManagerService經過Binder進程間通訊機制通知Launcher進入Paused狀態;
  3. Launcher經過Binder進程間通訊機制通知ActivityManagerService,它已經準備就緒進入Paused狀態,因而ActivityManagerService就建立一個新的進程,用來啓動一個ActivityThread實例,即將要啓動的Activity就是在這個ActivityThread實例中運行;
  4. ActivityThread經過Binder進程間通訊機制將一個ApplicationThread類型的Binder對象傳遞給ActivityManagerService,以便之後ActivityManagerService可以經過這個Binder對象和它進行通訊;
  5. AMS通知ActivityThread對象中調用bindApplication()方法. 送到消息隊列中, 最終經過handleBindApplication()方法處理該消息. 而後調用makeApplication()方法來加載Application的classes到內存中,而後通知AMS。
  6. ActivityManagerService經過Binder進程間通訊機制通知ActivityThread,能夠真正執行Activity的啓動。

Launcher啓動過程

  1. SystemServer進程啓動ActivityManagerService服務實例,添加到ServiceManager(負責管理系統中的Binder對象)
  2. ActivityManagerService向PackageManagerService查詢Category類型爲HOME的Activity,經過 ActivityStack.startActivityLocked將Launcher啓動起來
  3. Launcher在onCreate()中,經過這個PackageManagerService.queryIntentActivities接口來取回全部Action類型爲Intent.ACTION_MAIN,而且Category類型爲Intent.CATEGORY_LAUNCHER的Activity。顯示這些到頁面上。

Activity啓動流程

  1. AMS建立新進程,建立ActivityThread實例,將ApplicationThread的Binder對象傳遞給AMS而且開始了消息循環。
  2. 重新進程調用到ActivityManagerService進程中,獲取要在新進程啓動的服務的相關信息;
  3. 從ActivityManagerService進程又回到新進程中,最終將服務啓動起來。
    3.1. performLaunchActivity()初始化Activity
     3.1.1 classLoader加載Activity類,mInstrumentation.newActivity實例化Activity
     3.1.2 makeApplication若是進程中沒有就從新建立
     3.1.3 Activity.attach()將上下文信息設置到Activity中 包括window建立
     3.1.4 mInstrumentation.callActivityOnCreate->onCreate()調用setContentView爲decorView設置頁面內容
     3.1.5 Instrumentation.callActivityOnStart->onStart() 初始化應用數據準備
    3.2 handleResumeActivity激活Activity
     3.2.1 mInstrumentation.callActivityOnResume->onResume()作準備顯示到交互的處理
     3.2.2 wm.addView添加window的decorView開始繪製顯示頁面交互

Service啓動流程

service將計算型的邏輯單獨放在一個進程內執行提升用戶體驗。socket

start流程ide

  1. AMS建立新進程(會判斷ProcessRecord不存在纔去建立),建立ActivityThread實例,將ApplicationThread的Binder對象傳遞給AMS而且開始了消息循環。
  2. 重新進程調用到ActivityManagerService進程中,獲取要在新進程啓動的服務的相關信息;
  3. 從ActivityManagerService進程又回到新進程中,最終將服務啓動起來。
    3.1 handleCreateService()初始化Service
     3.1.1 經過ClassLoader加載service類,而後的newInstance實例化Service
     3.1.2 makeApplication若是進程中沒有就從新建立
     3.1.3 service.attach() 上下文信息設置到service中
     3.1.4 service.onCreate()回調
  4. 而後還會回新進程ApplicationThread.scheduleServiceArgs在主線程中回調onStartCommand

bind流程函數

  1. MainActivity調用bindService函數通知ActivityManagerService,它要啓動CounterService這個服務,ActivityManagerService因而在MainActivity所在的進程內部把CounterService啓動起來,而且調用它的onCreate函數;
  2. ActivityManagerService把CounterService啓動起來後,繼續調用CounterService的onBind函數,要求CounterService返回一個Binder對象給它;
  3. ActivityManagerService從CounterService處獲得這個Binder對象後,就把它傳給MainActivity,即把這個Binder對象做爲參數傳遞給MainActivity內部定義的ServiceConnection對象的onServiceConnected函數;
  4. MainActivity內部定義的ServiceConnection對象的onServiceConnected函數在獲得這個Binder對象後,就經過它的getService成同函數得到CounterService接口。

PhoneWindow流程

  1. 在Activity的attach中建立PhoneWindow並完成相關設置
    1.1 調用PolicyManager.makeNewWindow建立PhoneWindow,
    1.2 設置window的Calback將IO輸入事件分發給Activity(softMode設置)
    1.3 設置windowManager,mAppToken爲ActivityManagerService側ActivityRecord(Binder對象),mAppName爲Activity組件名稱
  2. 在onCreate中的setContentView(rId)完成window的視圖內容的設置
    2.1 installDecor()根據Theme和Feature完成window的頂級視圖mDecor以及找到mContentParent
    2.2 經過mLayoutInflater.inflate(layoutResID, mContentParent)設置到mContentParent中
  3. 在handleResumeActivity()中wm.addView()將window的內容繪製出來
    3.1 WindowManagerImpl.addView將decorView、viewRoot、LayoutParamas分別添加到mViews[i]、mRoots[i]和mParams[I]中
    3.2 viewRootImpl.setView()完成相關成員的配置工做和繪製
     3.2.1 將decorView設置到mAttachInfo.mRootView上
     3.2.2 panelParentView不爲空表示window是子窗口,須要保存ApplicationWindowToken到mAttachInfo中
     3.2.3 調用requestLayout()執行view樹的繪製流程

View繪製流程

  1. viewRootImpl的requestLayout()和invalidateChildInParent()最終都調用performTraversals()開始執行測量、佈局、繪製
  2. mView.measure測量全部view的寬高 這裏就比按照流程敘述了,按照我本身的通俗的理解來說
    前言:view測量時有限制MeasureSpec。本身的申請(layout_)告訴父親,父親根據本身的狀況計算家裏的狀況給出的錢(空間)的使用限制。Mode:家裏的狀況,Size:到手錢 本身當爸爸了 viewGroup(詳情getChildMeasureSpec)
家裏的狀況 Mode,拿到手上有 size大小的錢
  1.無論家裏任何狀況,只要兒子申請花調固定的數字childDimension>=0,超過限制也給,
兒子的Mode=EXACTLY,Size=childDimension
  2.其餘的話看家裏狀況
            都用掉 EXACTLY: 
                  兒子申請都給我吧 MATCH_PARENT:目標明確,給。兒子的Mode=EXACTLY,Size=size
                  兒子申請我本身算 WRAP_CONTENT:兒子的Model=AT_MOST,Size=size
        家裏手頭緊不能超過 AT_MOST:
                  無論兒子申請 MATCH_PARENT 仍是 WRAP_CONTENT:告訴子孫們手頭緊Mode=AT_MOST,Size=size
         不知道啥狀況,可是手動有錢 UNSPECIFIED:
                 無論兒子申請 MATCH_PARENT 仍是 WRAP_CONTENT:告訴子孫們家裏不知道啥狀況Mode=UNSPECIFIED,Size=size      
複製代碼

本身絕育了View,祖宗傳下來過日子之法 (詳情resolveSize)佈局

看家裏狀況
            要你都用掉 EXACTLY: 
                  都用光
        家裏手頭緊不能超過 AT_MOST:
                  本身用多少算多少吧,不超過就行
         不知道啥狀況,可是手動有錢 UNSPECIFIED:
                   沒限制,本身用多少算多少
複製代碼
  1. mView.layout 遞歸View樹 根據viewGroup的layout規則設置全部子View的位置
    3.1 ViewGroup必須重寫onLayout,根據排列規則以及measure測量的寬高調用child.layout對子View進行設置
    3.2 View的layout中調用setFrame完成對mLeft、mTop、mRight和mBottom賦值
    總結:全部的View都得靠父佈局經過本身的margin等相對規則肯定位置
  2. mView.draw 遞歸View樹繪製全部view到canvas上
    4.1 draw()控制總體繪製流程,可被重寫
    4.2 drawBackground()繪製背景,不可被重寫
    4.3 ondraw()繪製主體,可被重寫
    4.4 dispatchDraw() 主要給ViewGroup重寫分配給子View繪製,可重寫
    4.5 繪製滾動條和前景 在6.0合併到onDrawForeground(),可被重寫

ps:其實還有一個draw被ViewGroup經過drawChild調用,這個draw拿到的canvas是完整的父View的canvas,應用view動畫的矩陣以後在整個canvas裏裁剪對應view位置和大小的一塊canvas交給處理view自身繪製流程的draw方法學習

應用事件分發流程

經過View樹傳遞觸摸事件,一旦有View消費掉事件就不會繼續向下傳遞,若是沒有消費掉就會往上拋交給父View處理。down事件被View消費以後,後面連續的事件都會交給它處理。動畫

  • Activity事件分發
  1. phoneWindow將事件回調Activity的dispatchTouchEvent()分發事件
  2. 若是Event是ACTION_DOWN的狀況下會接着觸發onUserInteraction方法。
  3. 分發給mContentParent的子View處理事件
  4. 若子view攔截了事件(返回true)則Activity.onTouchEvent方法就不會執行。
  • ViewGroup事件分發
  1. dispatchTouchEvent 分發處理事件
  2. 經過disallowIntercept先判斷子View是否不讓ViewGroup攔截事件
  3. onInterceptTouchEvent()判斷當前ViewGroup是否須要攔截該事件
  4. 不攔截就直接dispatchTransformedTouchEvent()分發給子View處理,若是子View沒有處理就繼續交給本身邏輯
  5. 攔截就交給本身處理,交給super.dispatchTochEvent()處理
  • View事件分發
  1. dispatchTouchEvent 分發處理事件
  2. 若是view可用則調用mOnTouchListener(可消費調觸摸事件)
  3. 在onTochEvent中處理事件
    3.1 若是view是disable且是cliable 則直接消費調事件
    3.2 若是是enable且discliable直接返回 不消費事件
    3.3 若是是enable且cliable則處理消費事件邏輯,如up事件就會觸發clickListner

總結:view要消費調Down事件纔會接受到後續事件,而事件達到view時能夠被責任鏈裏的ViewGroup攔截掉,一旦攔截掉後續的任何一個事件對View來講就不完整了,因此爲了保證view能夠獲取全部事件,能夠聲明不讓他們攔截本身的事件。本身也不要在onTouchListner裏隨便攔截會影響onTouchEvent的正常處理的。若是沒有view處理就會向上繼續傳播處理spa

部分學習自老羅的博客

相關文章
相關標籤/搜索