手动实现最简单的Android热修复(最新最全详细小白教程)

前言

最近了解到了热修复相关的东西,于是很好奇原理,便一番搜索资料,同时为了加深对热修复的理解,便自己照着网上的例子去实现一个热修复,因为基础相对比较差,而且网上很多例子都是过时的,而且很多细节不注意到的话,就是一个坑,而且还五花八门的,于是我觉得将自己的这个实现热修复的例子记录下来事很有必要的,主要是参考并综合了网上很多热修复的例子,自己实现并完成整个从0到1的过程,好了,我们开始吧!

需要知道的基本概念和原理

首先是热修复的基本概念,我不太喜欢那种专业术语的描述方式,因为那样很容易让人觉得晦涩难懂,而且我觉得唯一的效果就是营造出一种初学者觉得高大上的装X效果而已,所以我就说下我的理解:假定一个场景,你的APP上线了,现在发现了一个小Bug,这个Bug很简单,可能是一行代码的事,但是由于你才上线,要是再重新打包你的APP再上线,这个过程就很麻烦了,于是我们期望有一种方式,不需要用户来重新安装新的APP即可运行我们修复了Bug的APP,这种方式就叫热修复。
是不是觉得很神奇。我也是,在没接触之前,我也觉得很神奇,但是明白之后,其实真的没什么,很简单。
再说下热修复的基本原理,这里很多网上的讲解非常的专业,我看了之后也理解了好久,但是自己再梳理一下,其实没有那么难理解,我还是以通俗的方式来说:
假设有一个数组,这个数组,里面有很多个dex文件(不了解的只需要知道里面就是存放了类的二进制数据,用来给安卓虚拟机加载),然后安卓虚拟机在加载类文件的时候,会有个顺序,我们暂且不用管是什么顺序,或者是怎么加载的,我们只需要知道,它会有顺序,我们假定它从数组下标为0的地方开始循环找,一旦找到了对应的文件,那么后面即便仍然还有该类的dex文件,也不去加载了,相当与前面加载的会覆盖后面的,就是这样一个原理。
那么实际中,可以怎么实现呢,我们可以将相应的dex文件放在服务器上,然后在用户不知道的情况下(可以在欢迎界面扫描服务器山的文件,如果有则下载进行热修复,否则不管),将这个dex文件从服务器上下载下来,并移动到指定位置即可。
我们也不需知道具体移动到哪里了,只知道移动的地方需要满足的条件是:在对应的类的dex文件加载顺序之前。这样就可以实现覆盖效果,让新的类文件比旧的类文件先加载,旧的就不会生效,达到我们想要的效果。

动手实现

在动手实现前,需要知道的事:
上面我们说了一种方案是从服务器上下载对应的dex文件,这里因为只是模拟一下效果,便采用手动复制对应的dex文件到指定目录下,来达到同样的效果。
开始吧:
首先我们新建工程,随便写一个Bug,比如我这里除数为0的Bug

public class TestCaculate {

    public int a = 10;
    public int b = 0;

    public void caculate(Context context) {
        Toast.makeText(context, "结果" + a / b, Toast.LENGTH_SHORT).show();
    }
}

当我们调用caculate方法时肯定会提示异常导致退出,现在我们以热修复的方式来修复Bug。
首先我们需要生成的文件就是我们修复好Bug的程序的dex文件,看清楚了,是修复好Bug的,代表什么意思呢,也就是在进行下一步之前,TestCaculate代码是这样的

public class TestCaculate {

    public int a = 10;
    public int b = 1;//已经修复

    public void caculate(Context context) {
        Toast.makeText(context, "结果" + a / b, Toast.LENGTH_SHORT).show();
    }
}

然后我们在布局文件中添加二个按钮,一个按钮点击调用caculate方法,触发Bug,另一个按钮点击修复Bug,需要注意的是,千万不要忘记了权限的申请,因为整个过程涉及到文件的读取和写入,而6.0以上需要动态获取权限,所以要在清单文件中加入下列两行代码。

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

MainActivity代码如下

public class MainActivity extends AppCompatActivity {

    private Button btn, btn_fix;

    public static final int REQUEST_CODE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn = findViewById(R.id.btn);
        btn_fix = findViewById(R.id.btn_fix);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                TestCaculate testCaculate = new TestCaculate();
        
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值