Android插件化-Activity替換

因為Activity的特殊性,activity的class被classLoader加載之后是可以當普通類使用了,但是生命周期需要系統(tǒng)回調(diào)。而且activity的啟動過程比較復雜,不是一個簡單的類加載和反射的過程。
為實現(xiàn)Activity的生命周期,實現(xiàn)方案都需要預先在宿主中占位,插件化技術發(fā)展到現(xiàn)在,為了輕量化,目前主流的實現(xiàn)方案有兩種:

  1. 替換Class loader
  2. 替換Instrumentation

Activity啟動過程

要實現(xiàn)這兩種方案,先要了解Activity的啟動過程

Activity_start.png
  • AMS: 即ActivityManagerServices,服務端對象,負責系統(tǒng)中所有Activity的生命周期
  • ActivityThread:App的入口,當開啟App之后,會調(diào)用main()開始運行,開啟消息循環(huán)隊列。就是主線程。
    與ActivityManagerServices配合,一起完成Activity的管理工作。
  • Instrumentation: 應用內(nèi)單實例對象,負責Activity的創(chuàng)建和暫停
  • ApplicationThread:負責ActivityManagerService與ActivityThread之間的交互。在ActivityManagerService需要管理相關Application中的Activity的生命周期時,通過ApplicationThread的代理對象與ActivityThread通訊
  • ApplicationThreadProxy: ApplicationThread在服務器端的代理,負責和客戶端的ApplicationThread通訊。AMS就是通過該代理與ActivityThread進行通信的
  • ActivityStack:Activity在AMS的棧管理,用來記錄已經(jīng)啟動的Activity的先后關系,狀態(tài)信息等。通過ActivityStack決定是否需要啟動新的進程

啟動流程簡述

  1. 先通過Instrumentation檢查對應的Activity是否已經(jīng)啟動,若已經(jīng)啟動切符合條件則直接返回。沒有在調(diào)用AMS去啟動activity
  2. AMS調(diào)用ActivityStarter啟動Activity。ActivityStarter先解析Intent中Activity的信息。查詢系統(tǒng)中是否有符合要求的Activity
  3. 使用合適的ActivityStack和 launch flags 來啟動 Activity, 如果存在可以直接恢復 Activity,則恢復,否則重新啟動 Activity
  4. 如果此時Activity所在的App未啟動,則先創(chuàng)建對應的App進程
  5. 若要啟動新的Activity,AMS會通過binder調(diào)用App進程,使用 ActivityThread 去執(zhí)行啟動,
  6. Instrumentation對過反射生成Activity的實例
  7. 使用handler來調(diào)用新生成的Activity的生命周期

替換Class loader

實現(xiàn)過程

  1. 自定義一個PathClassLoader,App啟動時將自定義的ClassLoader替換系統(tǒng)的ClassLoader
  2. 解析啟動插件Activity的intent,找到插件中對應的Activity class
  3. 分配與要啟動的Activity的啟動方式一致的坑位Activity,并保持兩個Activity的關聯(lián)
  4. 讓系統(tǒng)啟動坑位的Activity, 系統(tǒng)會使用替換過的ClassLoader加載坑位的Activity
  5. 替換過的ClassLoader啟動坑位的Activity時,通過對應的關聯(lián)找到對應的插件中的activity,
    找到后加載并返回
  6. android系統(tǒng)拿到的Activity就是插件中的activity, 然后調(diào)用它的生命周期

替換Instrumentation

這個方案比較簡單和輕量,由于activity的啟動和反射都是在Instrumentation中進行的,所以只hook啟動和反射生成實例的程就可以將占位的activity替換為插件中的Activity

實現(xiàn)過程

  1. 封裝一個Instrumentation,重寫啟動Activity的方法
  2. 將啟動的插件中的Activity替換為占位的activity
  3. 重寫Instrumentation的newActivity方法,使用插件的class loader 反射生成插件的activity
  4. 然后將封裝的Instrumentation替換掉宿主中的Instrumentation

這樣宿主啟動的acticity最終被替換成了插件中的activity,生命周期完全由系統(tǒng)管理。
但是由于啟動方式多樣性,所以占坑的時候需要埋入比較多的占坑Acttivity來應對不同的啟動方式
這個方案的過程比較簡單,而且hook的點很少,所以很輕量

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容