Android Studio點選Run背後發生了什麼?

水恆濤發表於2020-03-27

系列文章

  1. Android Gradle原理解釋
  2. Android Studio點選Run背後發生了什麼?

前言

我們知道在Android Studio中點選執行按鈕(下圖中的Run)即可對編寫的程式碼進行編譯,打包(生成APK),安裝APK到目標裝置,執行APP。這一系列流程背後都是Gradle這個構建工具幫我們在做工作,有關Gradle的基本知識已經在Android Gradle原理解釋一文中做了很多介紹。

Android Studio Run

本文我們換個角度,從點選按鈕這一行為出發來研究背後的具體流程和原理。除了Run按鈕外,還有build,Apply Changes, Debug等按鈕也做了類似工作,但應用場景不同。

build按鈕:對應的是Make Project,編譯Project下所有Module,一般是自上次編譯後Project下有更新的檔案,不生成apk。

Apply Changes按鈕:將程式碼和資源更改推送到正在執行的應用,而無需重啟應用(在某些情況下,無需重啟當前 Activity),是Instant Run功能的替代者。

Debug按鈕:在除錯模式下部署應用,在除錯模式下執行應用可在程式碼中設定斷點、在執行時檢查變數和對錶達式求值,以及執行除錯工具

Run按鈕背後流程

Run背後的Gradle tasks

Gradle生命週期分為三個階段,分別是Initialization(初始化階段),Configuration(配置階段),和Execution(執行階段),而執行階段會執行一系列task,進行主要的構建工作

那麼自然Run按鈕背後的構建工作也是由一系列task組成的,那麼我們有辦法去檢視這些task都有哪些麼?Android Studio提供了強大的日誌記錄功能,主要需要進行以下3步工作:

  1. 點選View > Tool Windows > Build,將在Android Studio介面下方顯示Build過程
  2. 點選右下角的EventLog按鈕
  3. 點選Run按鈕

完成上述點選後,等待APK安裝並執行完成,可以在Android Studio介面下方見到如下日誌:

run_log.png

Tasks名稱

> Task :app:preBuild UP-TO-DATE
> Task :app:preDebugBuild UP-TO-DATE
> Task :app:generateDebugBuildConfig UP-TO-DATE
> Task :app:javaPreCompileDebug UP-TO-DATE
> Task :app:mainApkListPersistenceDebug UP-TO-DATE
> Task :app:compileDebugRenderscript NO-SOURCE
> Task :app:compileDebugAidl NO-SOURCE
> Task :app:generateDebugResValues UP-TO-DATE
> Task :app:generateDebugResources UP-TO-DATE
> Task :app:mergeDebugResources UP-TO-DATE
> Task :app:createDebugCompatibleScreenManifests UP-TO-DATE
> Task :app:extractDeepLinksDebug UP-TO-DATE
> Task :app:processDebugManifest
> Task :app:processDebugResources
> Task :app:compileDebugJavaWithJavac UP-TO-DATE
> Task :app:compileDebugSources UP-TO-DATE
> Task :app:mergeDebugShaders UP-TO-DATE
> Task :app:compileDebugShaders UP-TO-DATE
> Task :app:generateDebugAssets UP-TO-DATE
> Task :app:mergeDebugAssets UP-TO-DATE
> Task :app:processDebugJavaRes NO-SOURCE
> Task :app:mergeDebugJavaResource UP-TO-DATE
> Task :app:dexBuilderDebug UP-TO-DATE
> Task :app:checkDebugDuplicateClasses UP-TO-DATE
> Task :app:mergeExtDexDebug UP-TO-DATE
> Task :app:mergeDexDebug UP-TO-DATE
> Task :app:mergeDebugJniLibFolders UP-TO-DATE
> Task :app:mergeDebugNativeLibs UP-TO-DATE
> Task :app:stripDebugDebugSymbols UP-TO-DATE
> Task :app:validateSigningDebug UP-TO-DATE
> Task :app:packageDebug
> Task :app:assembleDebug
複製程式碼

上述tasks大概可分為五個階段:

  1. 準備依賴包(Preparation of dependecies):在這個階段gradle檢測module依賴的所有library是否就緒。如果這個module依賴於另一個module,則另一個module也要被編譯;
  2. 合併資源並處理清單(Merging resources and processing Manifest):打包資源和 Manifest 檔案;
  3. 編譯(Compiling):處理編譯器的註解,原始碼被編譯成位元組碼;
  4. 後期處理(Postprocessing): 所有帶 “transform”字首的task都是這個階段進行處理的;
  5. 包裝和出版(Packaging and publishing):library生成.aar檔案,application生成.apk檔案。

部分Tasks詳細說明

  1. mergeDebugResources解壓所有的 aar 包,並且把所有的資原始檔合併相關目錄裡;
  2. processDebugManifest把所有 aar 包裡的AndroidManifest.xml中的節點,合併到專案的AndroidManifest.xml中
  3. processDebugResources

a. 呼叫 aapt 生成專案和所有 aar 依賴的R.java b. 生成資源索引檔案 c. 輸出符號表

  1. compileDebugJavaWithJavac用來把 java 檔案編譯成 class 檔案

此過程可參考詳解Android Gradle生成位元組碼流程

下圖是詳細版的Android 構建過程,可對應上述系列tasks中的某些工作:

apk_build.png

相關文章