我系蒼王路媚。
這個系列的課程都是時下最熱門的開源框架的源碼分析骡和。
今次為大家?guī)淼氖荢mall的源碼分析
一個源碼代碼量這么大箍鼓,究竟從哪里開始分析才好呢崭参?
最想了解究竟是哪個github的有源碼模塊呢?
歡迎在留言區(qū)款咖,我們共同討論分享的源碼分析何暮。
歡迎瀏覽我之前的文章,有興趣可以參考一下铐殃,可以給個喜歡或者關(guān)注我的文章海洼,謝謝。
[Android]如何做一個崩潰率少于千分之三噶應(yīng)用app(9)-Small插件化
一.Small的啟動
1.首先了解一下Small的基本情況Small
?基本的使用方法富腊,我在我的[Android]如何做一個崩潰率少于千分之三噶應(yīng)用app(9)-Small插件化這個文件有基礎(chǔ)使用分析坏逢。
2.然后我們需要更深入了解Small的流程的話,你可以看到 github里面有提供DevSample的文件夾赘被,這才是真正源碼存在的地方是整。
你可以到Small最主要的源碼
3.首先分析一下Small的啟動流程
查看一下Application的代碼
Small.java是全部調(diào)用方法的入口,一般聲明為靜態(tài)方法民假。
setBaseUri設(shè)定基本的跳轉(zhuǎn)地址
setWebViewClient設(shè)置網(wǎng)頁的基本回調(diào)
Small.preSetup設(shè)定Small啟動的預(yù)設(shè)置
(1)registerLauncher注冊BundleLauncher到一個List里面
? ? ? ?ActivityLauncher, ApkBundleLauncher,WebBundleLauncher都繼承BundleLauncher抽象類
? ? ? ?ActivityLauncher是Activity的管理類
? ? ? ?這里需要說明一下浮入,Small依然是使用占坑的方式來事先聲明Actvity,這是很多插件化相同的做法
? ? ? ?ApkBundleLauncher是bundle加載的管理類
? ? ? ?WebBundleLauncher應(yīng)該是web頁面的管理類
? (2) ?回調(diào)用Bundle.onCreateLaunchers初始化每一個laucher
? ? ? 這里會調(diào)用ApkBundlesLauncher里面的onCreate函數(shù)
? ? ? 通過getActivityThread反射獲取ActivityThread的對象
? ? ? 反射獲取mInstumentation的屬性對象和再將自定義的InstrumentationWrapper替換掉原來的mInstumentation
? 這里會反射mCallback的對象替換成ActivityThreadHandlerCallback
? ? ? ?獲取App的provider列表
? ? ? ? 保存這些變量用于全局控制
(2)接下來是檢測是不是第一次啟動或者更新羊异,去檢測他的bundle的版本號
(3)然后獲取一些簽名的信息保存到sHostCertificates
4.Application啟動完成后LaunchActivity就是啟動頁就會開始初始化
?在onStart的聲明周期里調(diào)用Small.Setup的方法初始化舵盈,結(jié)束回調(diào)啟動Bundle里面聲明main的類
(1)她會調(diào)用Bundle里面的loaderLaunchableBundles的函數(shù)
? ? ? ? ? ? 然后啟動一個LoadBundleThread的線程加載
? ? ? ? ? ? ? ? ?然后調(diào)用setupLaunchers的函數(shù)啟動之前注冊的launcher的setup函數(shù)
(1)ActivityLauncher setUp是初始化一些已經(jīng)注冊號的Activity,加到sActivityClasses里面
(2)ApkBundleLauncher的setUp是是通過代理替換InvocationHandler球化,有看過Activity啟動的相關(guān)源碼都應(yīng)該知道是同過代理的方式封裝啟動的秽晚,這里面會通過wrapIntent的函數(shù)重新包裝intent替換成占坑的里面的Activity
通過記錄realClazz和sLoaderAcitivities里面匹配封裝intent
(3)WebBundleLauncher的setUp的方法,啟動一個新的android 本身的WebView
在Bundle.setupLaunchers的函數(shù)完成之后才會調(diào)用loadBundles
這里的getPatchManifestFile是獲取bundle.json這個文件
將bundle.json轉(zhuǎn)換成mainfestJson的String字符串
然后繼續(xù)調(diào)用loadBundles的方法
這里會繼續(xù)調(diào)用prepareForLaunch的方法
這里會繼續(xù)調(diào)用preloadBundle的方法來判斷筒愚,然后調(diào)用loadBundle方法
(1)調(diào)用ApkBundleLauncher的loadBundle方法赴蝇,會獲取bundle的包名,來初始化LoadedApk的一些信息
(2)還有AssetBundleLauncher(WebBundleLauncher繼承于它)的loadBundle
判斷是否可以轉(zhuǎn)換為可以調(diào)整的url地址
我們在Bundle.loadBundles的方法往下看,可以看到它會再分發(fā)到各個launcher在啟動加載
它會跳轉(zhuǎn)到ApkBundleLauncher作一些加載資源巢掺,dex和lib的一些操作
(1)這里可以看到它會調(diào)用ReflectAcclerator.mergeResources調(diào)用合并資源
? ? 通過addAssetPaths的方法反射把資源放到newAssetManager里面
? 然后反射資源到resource到mResourcesImpl的代理屬性里面
(2)使用ReflectAcclerator.ExpandDexPathList的方法來合并加載dex的列表
? ? ? ? 這里會通過makeDexElement來返回Elements的數(shù)組
然后通過fillDexPathList的方法來反射一些地址
然后最后通過expandArray的方法句伶,里面通過System.arraycopy的方法來寫入dex的內(nèi)容
(3)加載完resource和dex之后,會再加載lib陆淀,這里會調(diào)用ReflectAcclerator.ExpandNativeLibraryDirectoris的方法
?這里依然是反射一些lib的相關(guān)地址屬性考余,然后調(diào)用expandArray來完成加載
(4)這里還會加載Provider的內(nèi)容,直接就通過反射完成
Small的SetupProvider已經(jīng)在AndroidMainfest里面有聲明了轧苫,所以這里加載只是因為ApkBundleLaucher.onException添加的容錯處理(SetupProvider加載失敗的時候)
寫到這里楚堤,啟動的流程基本就到這里了。
下一節(jié)我這里會介紹Small的更新流程的源碼。
敬請期待I矶衅胀!!