热修复框架的核心技术主要有3类:代码修复、资源修复和动态链接库修复。
资源修复
很多热修复的框架的资源修复参考了Instant Run的资源修复原理,因此我们首先了解下Instant Run 的原理。Instant Run 的资源修复核心逻辑在MonkeyPatcher 的monkeyPatchExistingResources 方法中,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
|
public static void monkeyPatchExistingResources(Context context,String externalResourceFile,Collection<Activity> activityes){
... try{ AssetManager newAssetManager = (newAssetManager)newAssetManager.class.getConstructor(new Class[0]).newInstance(new Object[0]); Method mAddAssetPath = AssetManager.class.getDeclareMethod("addAssetPath",new Class[] {String.class}); mAddAssetPath.setAccessible(true); if (((Integer) mAddAssetPath.invoke(newAssetManager,new Object[]{ externalResourceFile})).intValue () == 0) { throw new IllegalStateException("Could not create new AssetManager"); if{activities != null){ for (Activity activity : activities) { Resources resources= activity.getResources() ; try { Field mAssets = Resources.class.getDeclareField("mAssets"); mAssets.setAccessible(true );
mAssets.set(resources,newAssetManager) ; Resources.Theme theme = activity.getTheme(); ... Field ma = Resources . Theme.class.getDeclaredField (” mAssets " ) ; ma.setAccessible(true); //将 Resources.Theme 的 mAssets 字段替换为 newAssetManager ma.set(theme,newAssetManager);//7 } catch (Throwable ignore) { } } }
|
可以看出,在注释1处创建了一个新的AssetManager,之后通过反射调用 addAssetPath 方法加载外部(SD卡)的资源。在注释4处遍历Activity 列表,得到每个Activity 的Resource ,在5处通过反射得到Resources 的AssetManager 类型的mAsset字段,并在注释6处改写mAssets字段的引用为新的 AssetManager。之后,将AssetManager 类型的mAssets 字段的引用全部替换为新创建的 AssetManager。所以,总共就是两个步骤:
- 创建新的 AssetManager ,通过反射调用 addAssetPath 方法加载外部的资源,这样
新创建的 AssetManager 就含有了外部资源。
- 将 AssetManager 类型的 rnAssets 字段的引用全部替换为新创建的 AssetManager。
代码修复
先写到这,后续有空再来。。。