黑技术:来教大家做一款永不崩溃的APP

本文介绍了一种在APP开发中防止程序崩溃的方法。通过在Application的onCreate方法中使用setDefaultUncaughtExceptionHandler和Looper.loop()结合的方式,可以捕获主线程和子线程的所有异常,并使APP在异常发生后仍能继续运行,提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

*前言:大家知道,在APP开发中,最头疼的莫过于闪退了,一旦出现这种问题可是要被老板关小黑屋的~~

思考 : 那么有没有一种办法让我程序永不崩溃呢?? 众里寻他千百度,立马去百度~~ 结果出现一大堆的广告或水文,就没个有用的! 所以经过自己的探讨和实测后,给大家分享这个成功方案!*

**解决方案:**大家都知道,平时开发中遇到最多的异常无非就是:空指针,json解析错误等异常,我们平时的做法通常是try/catch, if(null!=),这些
重复丑陋的东西说实话写的真心伤神!
那我有没有一种方式去统一捕获全局的异常呢? 答案是有! 执行下面这句!
(Thread.setDefaultUncaughExceptionHandler()),即可以全局捕获了!

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
      catchException();
    }
    private void catchException(){
        Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
              // 执行错误捕获日志!  (全局异常回调方法!)
                    Log.d("捕获异常子线程:", Thread.currentThread().getName() +
                            "在:" + e.getStackTrace()[0].getClassName());
                }
        );
    }
}

捕获是能捕获,但经本人测试, 异常捕获后APP就死机了!!! 我去~
所以,这里尝试在异常捕获回调中执行下面代码(重启APP):

 Intent LaunchIntent = getPackageManager().getLaunchIntentForPackage(getPackageName());
 LaunchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 startActivity(LaunchIntent);
 Process.killProcess(Process.myPid()); (不加这行代码会白屏,杀死程序)
 System.exit(0); (预防Process.killProcess未知bug,用java语言再杀一遍,保险!)

测试结果:在报异常后能成功重启,但是会屏幕一闪,然后再启动! (体验效果差~)

PS:这当然不是我们想要的结果,于是我再去苦苦寻找,终于找到如下方法!
同样是在Application的onCreate方法中去调用下面方法:

   private void catchException(){
        Thread.setDefaultUncaughtExceptionHandler((t, e) ->
            Log.d("捕获异常子线程:",Thread.currentThread().getName()+
                    "在:"+e.getStackTrace()[0].getClassName())
        );
        //下面是新增方法!
        new Handler(Looper.getMainLooper()).post(() -> {
            while (true){
                try {
                    Looper.loop(); //会先执行这个方法,然后在执行下面的异常捕获方法!
                } catch (Exception e) {
                    Log.d("捕获异常主线程:",Thread.currentThread().getName()+"在:"+e.getStackTrace()[0].getClassName());
                    e.printStackTrace();
                }
            }
        });
    }

意思就是执行了一个Looper.loop的无限循环,然后再用try/catch包起来!
测试结果:无论APP哪里报异常都能继续流程执行! (不会卡顿,体验效果好)

而且我试了两种捕获方法分别的用处得出结论如下:
1.当我只使用setDefaultUncaughtExceptionHandler方法时,主线程和子线程的异常都能捕获! 但如果在回调不做任何处理APP会卡死!

2.当我只使用Looper.loop();捕获异常时,主线程的异常能正常捕获到,而且APP会正常运行! 但是子线程的异常依旧会闪退,即不能捕获!

3.当同时使用setDefaultUncaughtExceptionHandler和 Looper.loop()时,
主线程的异常会被Looper.loop()的try/catch接收,从而setDefaultUncaughtExceptionHandler中不会回调!
子线程的异常能被setDefaultUncaughtExceptionHandler回调,并且在抛出异常后结束子线程! (==>即无论主/子线程抛出异常,APP都能继续使用)

通过上面的两种方法融合,10来行代码!就能成功的打造了一个 永不崩溃的APP啦~~ 当然,只建议在生产环境适当考虑开启这个功能并将错误日志上传到服务器,测试阶段尽量不要开启,毕竟异常终究还是bug!

扩展:为什么while(true){Looper.loop()}
这行代码能捕捉主线程所有异常,并不同于setDefaultUncaughtExceptionHandler方式能让APP继续去运行呢?
详情见下回分晓,今天还有好多需求没实现555~ 感兴趣的朋友可去自行了解,也可抽空多来逛逛咱的博客!^_哈哈~
主要还是得去Android源码的启动入口去了解!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值