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