捕获程序Crash,让你的APP告别闪退

简介: 版权声明:本文为sydMobile原创文章,转载请务必注明出处! https://blog.csdn.net/sydMobile/article/details/78890196 文章最早发布于我的微信公众号 Android_De_Home 中,欢迎大家扫描下面二维码关注微信公众获取更多知识内容。
版权声明:本文为sydMobile原创文章,转载请务必注明出处! https://blog.csdn.net/sydMobile/article/details/78890196

文章最早发布于我的微信公众号 Android_De_Home 中,欢迎大家扫描下面二维码关注微信公众获取更多知识内容。
可以随意转载,但请务必注明出处!

为什么出现这种方法

当APP在线程中跑出了异常就会导致APP crash。比如我们最常见的NullPointerException空指针异常。有些时候我们不希望这种异常导致我们的APP crash,尤其是在debug状态下,程序很大的时候,编译运行一次也不容易,debug的时候好不容易程序启动起来了,发生了crash就不能debug执行了,有时候会很耽误开发。所有有了这个自定义的异常处理。它可以捕获你的异常,使程序不会crash,这样就可以继续调试了。

具体操作介绍

首先介绍Thread.UncaughtExceptionHandler

UncaughtExceptionHandler文档

文档说明:当一个线程突然的因为没有捕获到的异常而停止的时候会由这个接口来处理。当一个线程由于没有捕获的异常而终止的时候,Java虚拟机将查询这个线程通过UncaughtExceptionHandler的getUncaughtExceptionHandler。并将调用uncaughtExcetion方法,并且把这个线程和异常作为参数传递过去。如果一个线程没有他的UncaughtExceptionHandler设置, 那么它的ThreadGroup对象作为它的UncaughtExceptionHandler。如果ThreadGroup对象没有特别的处理异常要求,它可以调用getDefaultUncaughtExceptionHandler。即系统默认的的
UncaughtExceptionHandler。

简单来说UncaughtExceptionHandler就是用于在线程中当一些系统没有捕获的异常发生的时候来处理这些异常的。你可以使用系统默认的处理方式,你也可以通过Thread.setDefaultUncaughtExceptionHandler()方法设置你自己定义的异常处理。

uncaughtException_method

注意Thread.setDefaultUncaughtExceptionHandler(CustomUncaughtExceptionHandler)后,只能保证当在你的程序中如果crash没有发生在UI线程(主线程)中而是在别的线程中的时候,这个时候APP是不会出现崩溃的现象的。如果在主线程中出现crash后,APP还是会崩溃的。

进一步防止程序出现Crash

开头已经说了,有很多时候虽然我们的APP会因为各种问题闪退,但是在更多的时候我们是不希望,我的APP闪退的这就出现了下面的方法。

首先说明这种方法在Activity初始化的时候可能会导致你的APP出现类似ANR的情况(其实并不是ANR,只是状态看起来像,造成的原因是因为Activity还没有完成初始化,也就是生命周期还没有执行完毕就遇到异常了,导致了页面没法显示,所以在正式发布的APP中还是要慎重使用)

如何使用呢?需要和你的后台商量好,在程序中做好标志控制该不该使用ExceptionHandler来处理。如果你的程序某个地方出现大量crash的时候,而这个功能是在Activity初始化后(可能是由于点击某个按钮触动的问题)这个时候你就可以用ExceptionHandler来处理了,让用户在点击这个按钮后,不至于程序崩溃掉。

核心代码:

     new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {

                while (true) {
                    try {
                        Looper.loop();
                    } catch (Throwable throwable) {



                    }
                }
            }
        });

通过Handler向主线程的queue中添加一个Runnabel(此处new Handler()里面传参数Looer.getMainLooper()就是为了是向主线程的queue中添加,如果不传这个参数就是默认的了)当主线程执行到我们发送的这个Runnable的时候就会进入我们的while死循环,如果while内部是空的话就会造成代码卡死在这里导致ANR,但是我们在while中调用了Looper.loop(),这就使得我们的主线程又开始工作了,不断的从queue中获取Message执行(其实Android的机制就是这样的不断的从主线程的queue中获取message并且执行)。这样就可以保证以后主线程的所有异常都会从我们手动调用的Looper.loop()处抛出了。

下面分析一下为什么这样就可以保证主线程的所有异常都会从我们手动调用的Looper.loop()处抛出。

ActivityThread_main()

首先看主线程的源码,我的主线程都是在main()函数里面开始执行的,就像Java一样,这里是入口。我们可以看到在main函数中调用了Looper.loop()。

Looper.loop()

Looper.loop()方法的源码,在这里就很明显了,我们可以看到在这个方法中有一个for(;;)死循环,不断的从queue中获取message执行。所以我们的方法就变成了

      for(;;){
            Message msg = queue.next();
            //如果msg是我们post过来的Runnable就会执行下面的代码了
            while(true){
                try{
                    Looper.loop();(的本质就是 for(;;){.....})
                }catch(....){
                    ........

                }

            }

        }

所以当出现异常的时候就会抛出了。所以这样做的话就可以保证所有主线程中的异常可以被捕获了,单纯这样做的话,子线程中如果出现问题的话还是会crash的,所以就要加上Thread.setDefaultUncaughtExceptionHandler()了。

原理基本就介绍完了,结合写的代码(代码里面有详细的使用注释)看会更清晰一些。代码地址和使用方法点击 这里

参考:https://github.com/android-notes/Cockroach ,谢谢!



扫一扫关注微信公众号,获取更多干货和资源 关注公众号,及时获取推送

目录
相关文章
|
6月前
|
存储 安全 Linux
【Azure 应用服务】App Service For Linux 怎么安装Composer,怎么安装PHP扩展,怎么来修改站点根路径启动程序?
【Azure 应用服务】App Service For Linux 怎么安装Composer,怎么安装PHP扩展,怎么来修改站点根路径启动程序?
|
9月前
|
开发工具 iOS开发
如何导出iPhone手机中app共享文件夹的文件与闪退日志的收集
如何导出iPhone手机中app共享文件夹的文件与闪退日志的收集
132 1
|
9月前
|
Android开发
Android修改默认system/bin/下可执行程序拥有者和权限,使用实例,只有root和系统app权限才能执行某个命令。
Android修改默认system/bin/下可执行程序拥有者和权限,使用实例,只有root和系统app权限才能执行某个命令。 【5月更文挑战第2天】
415 0
|
9月前
|
存储 Java Android开发
app应用程序进程启动过程
app应用程序进程启动过程
77 1
|
9月前
|
安全 开发工具 数据安全/隐私保护
如何将应用程序发布到 App Store
如何将应用程序发布到 App Store
|
9月前
|
存储 缓存 开发者
APP闪退的原因
APP闪退的原因
582 1
|
9月前
|
Android开发 iOS开发 开发者
点击APP的应用程序图标后,发生了什么
点击APP的应用程序图标后,发生了什么
116 1
|
9月前
|
PHP
HYBBS 表白墙网站PHP程序源码 可封装成APP
HYBBS 表白墙网站PHP程序源码 可封装成APP
79 1
|
9月前
|
安全 开发工具 数据安全/隐私保护
如何将应用程序发布到 App Store
如何将应用程序发布到 App Store
|
9月前
|
小程序 Linux 区块链
Python PyInstaller 打包成 Win、Mac 应用程序(app / exe)
Python PyInstaller 打包成 Win、Mac 应用程序(app / exe)
487 0

热门文章

最新文章

  • 1
    MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
  • 2
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    微信小程序 app.json 配置文件解析与应用
  • 4
    【Azure App Service】基于Linux创建的App Service是否可以主动升级内置的Nginx版本呢?
  • 5
    原生鸿蒙版小艺APP接入DeepSeek-R1,为HarmonyOS应用开发注入新活力
  • 6
    【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
  • 7
    【Azure Function】Function App出现System.IO.FileNotFoundException异常
  • 8
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 9
    【Azure Logic App】使用MySQL 新增行触发器遇见错误 :“Unknown column 'created_at' in 'order clause'”
  • 10
    阿里云APP备案流程图以及备案所需材料整理,跟着教程一步步操作
  • 1
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    33
  • 2
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    29
  • 3
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    23
  • 4
    【Azure Function】Function App门户上的Test/Run返回错误:Failed to fetch
    30
  • 5
    陪玩APP推送配置:陪玩系统手机锁屏收不到推送?可能是这些原因!解决方案来了!
    34
  • 6
    小游戏源码开发之可跨app软件对接是如何设计和开发的
    33
  • 7
    原生鸿蒙版小艺APP接入DeepSeek-R1,为HarmonyOS应用开发注入新活力
    134
  • 8
    PiliPala:开源项目真香,B站用户狂喜!这个开源APP竟能自定义主题+去广告?PiliPala隐藏功能大揭秘
    60
  • 9
    语音app系统软件源码开发搭建新手启蒙篇
    44
  • 10
    MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
    874