上
一:热修复背景
1,刚发布的版本出现了严重的Bug,这就需要去解决Bug、测试打包重新发布,这会耗费大量的人力和物力,代价比较大
2,已经更正了此前发布版本的Bug,如果下个版本是大版本,那么两个版本之间间隔时间会很长,这样要等到下个大版本发布再修复Bug,而之前版本的Bug会长期的影响用户
3,版本升级率不高,并且需要长时间来完成版本迭代,前版本的Bug就会一直影响不升级的用户
4,有一些小但是很重要的功能需要在短时间内完成版本迭代,比如节日活动
二:正常开发流程与热修复开发流程对比
三:热修复框架分类与对比
1,分类
阿里系:AndFix、Dexposed、阿里百川、Sophix
腾讯系:微信的Tinker、QQ空间的超级补丁、手Q的QFix
知名公司:美团的Robust、饿了么的Amigo、美丽说蘑菇街的Aceso
其它:RocooFix、Nuwa、AnoleFix
2,对比
四:代码修复
1,底层替换方案
在已加载的类中直接替换原有方法,是在原有类的基础上进行修改,无法实现对原有类进行方法和字段的增减,这样会破坏原有类的结构
最大问题是不稳定性,直接修改虚拟机方法实体的具体字段来实现的。Android是开源的,不同的手机厂商开源对代码进行修改,所以像Andfix就会出现在部分机型上的热修复失效的现象
2,类加载方案
APP重新启动后,让ClassLoader去加载新的类。
五:热修复优势
1,无需重新发布新版本,省时省力
2, 用户无感知修复,也无需下载最新应用,代价小
3, 修复成功率高,把损失降到最低
六:插桩原理
java文件被编译成字节码文件,然后在android中在进一步被编译成.dex文件。
DexClassLoader可以加载任何地方的dex文件,SD卡上的可以,应用私有目录也可以。出于安全考虑(有同名的危险),我们一般都放在私有目录里面
热修复就是把class打包成dex文件,把修复好的dex文件放到数组的第一位
七:dex分包
可以在multidex.keep中配置分包文件,哪些文件是主文件可以在这里定义
在gradle中设置
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.dn.lsn16_demo"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
// 开启分包
multiDexEnabled true
// 设置分包配置文件
multiDexKeepFile file('multidex.keep')
}
dexOptions {
javaMaxHeapSize "4g"
preDexLibraries = false
additionalParameters = [ // 配置multidex参数
'--multi-dex', // 多dex分包
'--set-max-idx-number=50000', // 每个包内方法数上限
'--main-dex-list=' + '/multidex.keep', // 打包到主classes.dex的文件列表
'--minimal-main-dex'
]
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:multidex:1.0.3'
}
(下)
八,我们看下手写怎么实现
这是我们的目录结构
现在Calculator中有一个bug,我们看下
package com.dn.lsn16_demo;
import android.content.Context;
import android.widget.Toast;
public class Calculator {
public void calculate(Context context){
int a = 666;
int b = 0;
Toast.makeText(context, "calculate >>> " + a / b, Toast.LENGTH_SHORT).show();
}
}
我们现在假设我们已经从服务器上把修复好的类下载到了本地