文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android 主线程崩溃与子线程崩溃有什么本质区别?你是怎么处理的?

2024-12-03 15:05

关注

问答环节

问:Android 主线程崩溃与子线程崩溃有什么本质区别?

答:子线程崩溃就是正常的 Java thread 样子,通过 setDefaultUncaughtExceptionHandler 就能捕获 ThreadGroup 里对应子线程的异常做后续处理(启动独立进程提醒用户并上报平台等,或者通过策略下发忽略特定异常当作没发生一样)。安卓中主线程的 Crash 和子线程 Crash 有一点差异,虽然本质都是通过 setDefaultUncaughtExceptionHandler 就能捕获,但是这背后其实是有一点窍门的。由于 Android 主线程启动后通过 MainHandler 的 Looper.loop() 一直保持管道阻塞式的生产消费者死循环,所有的主线程代码都是通过这个循环派发在 MainLooper 中执行的,所以当主线程 crash 的场景下,这个循环会被跳出,导致 Looper 无法再继续执行其中的其他 Message,所以当主线程 crash 时会出现几种不同的表现,场景的一种就是在 Activity 的 onCreate 中 crash 会导致界面黑屏(注意,这种 crash 不是 anr,是因为 onCreate 中抛出异常导致后续代码无法执行,也就是 Activity 生命周期框架代码无法继续,同时后续 Message 也无法正常派发,所以界面还没出来就黑屏了),而 View 点击事件响应中 crash 可能不会黑屏(也可能会,取决于做什么操作),但是后续 Message 也是无法正常派发。

拓展环节
问:针对上面描述你有什么想法?

答:子线程奔溃没啥说的,由于主线程发生了崩溃会导致 Looper 退出,所以我们可以在主线程启动一个我们自带 try-catch 的 Looper.loop() 去执行主线程任务,相当于这样我们通过带 try-catch 的 loop() 替换掉了 ActivityThread main 里面那个 Looper.loop(),这样就不会出现主线程崩溃后 loop 退出了,也就能继续执行代码了,只是当次 crash 的场景可能是无效的,譬如用户点击按钮设置文案 crash 了,点了可能没反应;同时点击按钮启动的 Activity 的 onCreate 等方法里面有 crash 则会导致黑屏,所以这种 crash 需要区分对待(譬如上报异常并弹框提醒并直接杀掉进程等)。

下面是核心代码的简单实现(Activity 生命周期处理的比较粗略,仅供 demo):

  1. // Application 启动就进行替换 
  2. new Handler(getMainLooper()).post(new Runnable() { 
  3.     @Override 
  4.     public void run() { 
  5.         // 每次蹦了就继续重新循环,保证永远都能 loop 
  6.         while (true) { 
  7.             try { 
  8.                 Looper.loop(); 
  9.             } catch (Throwable e) { 
  10.                 e.printStackTrace(); 
  11.                 // TODO 手动上报错误到异常管理平台,做交互处理等 
  12.                 if (e.getMessage() != null && e.getMessage().startsWith("Unable to start activity")) { 
  13.                     // TODO 来自 Activity 生命周期崩溃,杀死进程 
  14.                     android.os.Process.killProcess(android.os.Process.myPid()); 
  15.                     break; 
  16.                 } 
  17.             } 
  18.         } 
  19.     } 
  20. }); 


当然,针对 Activity 生命周期方法内的 crash 黑屏我们除过判断堆栈日志方式,还能通过 hook ActivityThread 的 mH 主 Handler 实现,将里面的 Message handle 函数托管我们实现,然后进行 try-catch 捕获,发现异常就 close 对应 Activity 或者 kill app 即可,这个方案其实网上有现成的开源库,大家可以去参考下。

本文转载自微信公众号「码农每日一题」,可以通过以下二维码关注。转载本文请联系码农每日一题公众号。 

 

来源:码农每日一题 内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯