Android Crash与ANR详细介绍

目录
  • Crash
  • 空指针
  • 角标越界
  • 集合元素删除操作
  • 异步操作后对界面元素的处理
  • Intent传递数据过大
  • 在子线程中操作UI
  • ANR

Crash

Crash是指程序闪退,导致APP不能正常使用。Crash产生的原因有很多,下面只是列举了一些常见原因。

空指针

空指针应该是项目中最容易产生crash的情况了,举个例子,我们获取某个对象的属性或方法时,这个对象为Null时,如何没有判空,则会出现空指针异常NullPointException,所以这就要求使用对象的时候进行非空判断,在这点,我觉得kotlin就做得很好,利用空安全可以很好地避免NullPointException。

角标越界

在使用数组或者集合的时候会出现IndexOutOfBoundsException,在根据index进行取值时,最好先判断该索引值是否存在或者使用try-catch捕捉异常。

集合元素删除操作

比如我们需要将集合中满足条件的元素删除掉

        list.forEach {
            if (it == 3) {
                list.removeAt(it)
            }
        }

这样做会引起Crash,会报ConcurrentModificationException,针对这个问题,我们可以从后面开始遍历

        for (index in list.size - 1 downTo 0) {
            if (list[index] == 3) {
                list.removeAt(index)
            }
        }

也可以使用迭代器进行遍历删除元素

        val iterator = list.iterator()
        while (iterator.hasNext()) {
            val a = iterator.next()
            if (a == 3) {
                iterator.remove()
            }
        }

当多个线程同时操作某个数组时,不要进行数组的增删改查等操作,这样同样也会引起相关的Crash或数据查询不准确等问题。

异步操作后对界面元素的处理

在fragment中使用Context前最好先加上判断isAdded判断,特别是异步操作后使用Context,很有可能出现报错(Fragment not attached to a context)而闪退,所有的异步回调后若要操作View,都要判断view是否为空,否则会出现界面销毁后View为空,空指针闪退问题。

Intent传递数据过大

Intent传512K以下的数据可以正常传递,高于512K则会出错,因为考虑到Intent还要包括要启动的Activity等信息,所以实际可以传的数据应该略小于512K。

        val data = ByteArray(1024 * 1024)
        val intent = Intent(this, ExpActivity::class.java)
        intent.putExtra("test", data)
        startActivity(intent)

这段代码会导致Crash

Caused by: android.os.TransactionTooLargeException: data parcel size 1049012 bytes

因为我们在Intent中携带的数据要从APP进程传输到AMS进程,再由AMS进程传输到目标Activity所在进程,普通的由 Zygote 孵化而来的用户进程,所映射的Binder内存大小是不到1M,但是,在使用Intent传递数据时,1M并不是安全上限,因为Binder可能正在处理其它的传输工作。总而言之,startActivity携带的数据会经过Binder内核再传递到目标Activity中去,因为binder映射内存的限制,所以startActivity也会这个限制。

在子线程中操作UI

子线程中是不能操作UI的,如果在子线程中某个时机想要改变UI,可以使用Handler或者kotlin协程切换,需要注意的是,在子线程中也不可以操作Dialog和Toast。但是,这有个很有意思的点,举个例子,如果你在onCreate中开启一个子线程改变UI,会发现程序运行正常,没报错,像这样

class ExpActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_exp)
        val name = findViewById<TextView>(R.id.name)
        Thread { name.text = "name" }.start()
    }
}

但是,你延迟一秒后再操作UI,又会闪退报错

class ExpActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_exp)
        val name = findViewById<TextView>(R.id.name)
        Thread {
            Thread.sleep(1000)
            name.text = "name"
        }.start()
    }
}

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

这到底是为什么呢?这个的关键是ViewRootImpl类,它会去检查当前线程是不是主线程,如果不是就会抛出异常。像上面的情况,在onCreate中未延时直接操作UI不闪退,是因为此时ViewRootImpl还没有被初始化,这个时候程序没有去检测当前线程是不是主线程,所以没有抛异常。严格地讲,在ViewRootImpl构造的时候赋值的,赋值的就是当前的Thread对象,也就是说,你ViewRootImpl在哪个线程创建的,你后续的UI更新就需要在哪个线程执行,跟是不是UI线程毫无关系。

ANR

ANR是指程序未响应,在Android系统中,AMS和WMS会检测App的响应时间,如果App在特定时间无法响应屏幕触摸或键盘输入事件,或者特定事件没有处理完毕,就会出现ANR。

不同Context规定的上限时间不同:

  • 主线程对输入事件5秒内没有处理完毕。
  • 主线程在执行BroadcastReceiver的onReceive()函数时10秒内没有处理完毕。
  • 主线程在Service的各个生命周期函数时20秒内没有处理完毕。

避免ANR就要尽量避免在主线程中做耗时操作,耗时操作尽量放在子线程中。

我们可以通过/data/anr/traces.txt文件来分析ANR的产生,通过adb命令可以导出该文件,不过traces文件记录的东西可能比较多,分析的时候需要针对性地搜索出相关记录,该文件会记录进程ID,包名,造成ANR的原因和产生ANR的具体行数。

到此这篇关于Android Crash与ANR详细介绍的文章就介绍到这了,更多相关Android Crash与ANR内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入学习Android ANR 的原理分析及解决办法

    目录 一.ANR说明和原因 1.1 简介 1.2 原因 1.3 避免 二.ANR分析办法 2.1 ANR重现 2.2 ANR分析办法一:Log 2.3 ANR分析办法二:traces.txt 2.4 ANR分析办法三:Java线程调用分析 2.5 ANR分析办法四:DDMS分析ANR问题 三.造成ANR的原因及解决办法 四.ANR源码分析 4.1 Service造成的Service Timeout 4.2 BroadcastReceiver造成的BroadcastQueue Timeout 4.

  • 浅谈Android ANR的信息收集过程

    目录 一. ANR场景 二. appNotResponding处理流程 三. 总结 一. ANR场景 无论是四大组件或者进程等只要发生ANR,最终都会调用AMS.appNotResponding()方法,下面从这个方法说起. 以下场景都会触发调用AMS.appNotResponding方法: Service Timeout:比如前台服务在20s内未执行完成: BroadcastQueue Timeout:比如前台广播在10s内未执行完成 InputDispatching Timeout: 输入事

  • Android广播事件流程与广播ANR原理深入刨析

    目录 序言 一.基本流程和概念 二.无序广播流程 注册广播接收者流程 广播通知流程 三.有序广播流程 四.广播ANR流程 五.总结 六.扩展问题 序言 本想写广播流程中ANR是如何触发的,但是如果想讲清楚ANR的流程,就不得不提整个广播事件的流程,所以就把两块内容合并在一起讲了. 本文会讲内容如下: 1.动态注册广播的整个分发流程,从广播发出,一直到广播注册者接收. 2.广播类型ANR的判断流程和原理. PS:本文基于android13的源码进行讲解. 一.基本流程和概念 动态广播的流程其实是很

  • Android Java crash 处理流程详解

    目录 一.背景 二.App端Crash注册 2.1 commonInit() 2.2 KillApplicationHandler 类 2.2.1 ensureLogging() 2.2.2 ApplicationErrorReport 三.AMS端处理崩溃逻辑 3.1 AMS.handleApplicationCrash 3.1.1 AMS.handleApplicationCrashInner() 3.2 addErrorToDropBox() 3.3 AppErrors.crashAppl

  • Android性能优化之捕获java crash示例解析

    目录 背景 java层crash由来 为什么java层异常会导致crash 捕获crash 总结 背景 crash一直是影响app稳定性的大头,同时在随着项目逐渐迭代,复杂性越来越提高的同时,由于主观或者客观的的原因,都会造成意想不到的crash出现.同样的,在android的历史化过程中,就算是android系统本身,在迭代中也会存在着隐含的crash.我们常说的crash包括java层(虚拟机层)crash与native层crash,本期我们着重讲一下java层的crash. java层cr

  • 解析Android ANR问题

    一.ANR介绍 ANR 由消息处理机制保证,Android 在系统层实现了一套精密的机制来发现 ANR,核心原理是消息调度和超时处理.ANR 机制主体实现在系统层,所有与 ANR 相关的消息,都会经过系统进程system_server调度,具体是ActivityManagerService服务,然后派发到应用进程完成对消息的实际处理,同时,系统进程设计了不同的超时限制来跟踪消息的处理. 一旦应用程序处理消息不当,超时限制就起作用了,它收集一些系统状态,譬如 CPU/IO 使用情况.进程函数调用栈

  • Android app会crash的原因及解决方法

    android main入口的commonInit()方法内处,有这么一句话, Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler)); 如果没有这句话,app就不会crash.不信,你往里面看, public KillApplicationHandler(LoggingHandler loggingHandler) { @Override public void uncaught

  • Android性能优化之ANR问题定位分析

    目录 前言 1 ANR原因总结 1.1 KeyDispatchTimeout 1.2 BroadCastTimeout 1.3 ServiceTimeout 1.4 ContentProviderTimeout 2 ANR问题解决 2.1 线下问题解决 2.2 线上问题解决 2.2.1 Bugly 2.2.2 FileObserver 2.2.3 WatchDog 前言 ANR(Application Not Response)应用程序未响应,当主线程被阻塞时,就会弹出如下弹窗 要么关闭当前ap

  • Android 应用Crash 后自动重启的方法小结

    前提 首先,我们肯定要在Application里面注册一个CrashHandler,监听应用crash public class TestApplication extends MultiDexApplication { private static TestApplication mInstance; @Override public void onCreate() { super.onCreate(); Thread.setDefaultUncaughtExceptionHandler(ne

  • Android Crash与ANR详细介绍

    目录 Crash 空指针 角标越界 集合元素删除操作 异步操作后对界面元素的处理 Intent传递数据过大 在子线程中操作UI ANR Crash Crash是指程序闪退,导致APP不能正常使用.Crash产生的原因有很多,下面只是列举了一些常见原因. 空指针 空指针应该是项目中最容易产生crash的情况了,举个例子,我们获取某个对象的属性或方法时,这个对象为Null时,如何没有判空,则会出现空指针异常NullPointException,所以这就要求使用对象的时候进行非空判断,在这点,我觉得k

  • Android手机信号强度检测详细介绍

    最近到处在跑着找工作,难免在面试过程中遇到这样那样的问题,记得最清楚一次在面试过程中被问到,当手机处于弱网状态下,如何处理,如何监听网络信号强度变化.但是真是蒙了,回答的乱七八糟,思路一点都不明确.今天小编在这里带领大家了解下关于手机信号强度的相关几个概念. Android手机信号强度介绍 android定义了2种信号单位:dBm和asu.它们之间的关系是:dBm =-113+2asu,这是google给android手机定义的特有信号单位.例如,我的信号强度为-53dBm,则对应30asu,因

  • Android与H5互调详细介绍

    Android与H5互调详细介绍 微信,微博,微商,QQ空间,大量的软件使用内嵌了H5,这个时候就需要了解Android如何更H5交互的了:有些外包公司,为了节约成本,采用Android内嵌H5模式开发,便于在iOS上直接复用页面,最终解决成本. 为什么学android也要学h5? Android很多软件都有内嵌H5的,有什么用处.优势?节约成本,提高开发效率. 实现的原理是什么? 本质是:Java代码和JavaScript调用 案例一:Java与Js简单互调 首先,在Android代码中加载H

  • Android集成高德地图详细介绍

    最终效果是,本App展示地图,点击地图导航,调转三方实现导航. 1.迈出第一步,去创建自己的应用key https://lbs.amap.com/1.1创建完应用之后,点击页面的{添加},要求填写自己项目的信息 对于调试获取SHA1的方法是:1.打开cmd,2.在弹出的控制台窗口中输入 cd .android 定位到 .android 文件夹: 3.继续在控制台输入命令: 调试版本使用 debug.keystore,命令为:keytool -list -v -keystore debug.key

  • Android组件化原理详细介绍

    目录 什么是组件化? 为什么使用组件化? 一步步搭建组件化 1.新建模块 2.统一Gradle版本号 3.创建基础库 4.组件模式和集成模式转换 5.AndroidManifest的切换 6.*业务Application切换 组件之间的跳转 1.添加依赖 2.初始化ARouter 3.添加跳转 组件之间的数据传递 1.定义接口 2.实现接口 组件Application的动态切换 1.定义抽象类 BaseApplication 继承 Application 2.所有的组件的 Application

  • Android中的WebView详细介绍

    Android中WebView的详细解释: 1. 概念: WebView(网络视图)能加载显示网页,可以将其视为一个浏览器.它使用了WebKit渲染引擎加载显示网页. 2. 使用方法: (1).实例化WebView组件: A.在Activity中实例化WebView组件.eg: 复制代码 代码如下: WebView webView = new WebView(this); B.调用WebView的loadUrl()方法,设置WevView要显示的网页.eg: 复制代码 代码如下: 互联网用:we

  • Android Monkey压力测试详细介绍

    Monkey 是Android SDK提供的一个命令行工具, 可以简单,方便地运行在任何版本的Android模拟器和实体设备上. Monkey会发送伪随机的用户事件流,适合对app做压力测试 阅读目录 环境搭建 什么是Monkey Monkey 用来做什么 Monkey程序介绍 Monkey 架构 Monkey弱点 Monkey 参数大全 Monkey 命令 基本参数介绍 Monkey 实例 Monkey 查看包名 Monkey  日志分析 必须重视Crash 环境搭建 安装Android SD

  • Android Service总结及详细介绍

    1.Service的种类 按运行地点分类: 类别 区别  优点 缺点   应用 本地服务(Local) 该服务依附在主进程上,  服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL.相应bindService会方便很多.  主进程被Kill后,服务便会终止.  非常常见的应用如:HTC的音乐播放服务,天天动听音乐播放服务. 远程服务(Remote) 该服务是独立的进程,  服务为独立的进程,对应进程名格式为所在包名

  • Android广播接收机制详细介绍(附短信接收实现)

    Android中广播(BroadcastReceiver)的详细讲解. 1. BroadcastReceiver的注册过程: (1).广播消息发出来后,只有订阅了该广播的对象才会接收发出来的广播消息并做出相应处理. **(2).**Android广播分为两个方面:广播发送者和广播接收者.Android中的广播使用了观察者模式,基于消息的发布/订阅事件模型.广播接收者通过Binder机制向AMS进行注册,AMS查找符合相应条件的Broadcastreceiver,将广播发送到BroadcastRe

  • Android 中的注解详细介绍

    注解是我们经常接触的技术,Java有注解,Android也有注解,本文将试图介绍Android中的注解,以及ButterKnife和Otto这些基于注解的库的一些工作原理. 归纳而言,Android中的注解大概有以下好处 提高我们的开发效率 更早的发现程序的问题或者错误 更好的增加代码的描述能力 更加利于我们的一些规范约束 提供解决问题的更优解 准备工作 默认情况下,Android中的注解包并没有包括在framework中,它独立成一个单独的包,通常我们需要引入这个包. dependencies

随机推荐