Android(安卓)ANR问题定位
16lz
2021-01-26
- 什么是ANR
Appliction Not Responding 直译过来的意思就是应用程序没有响应
- ANR的产生原因, 及场景
原因: 在UI线程上执行一个潜在的耗时操作场景:1.KeyDipatchTimeout(5 seconds)-->按键或触摸事件在特定时间内没有响应2.BroadcastReceiver(10 seconds)-->在特定时间内无法处理完成3.ServiceTimeout(20 seconds)-->service在特定时间内没有完成
- 如何监测ANR
原理:Android应用程序的所有交互操作和响应,都是通过主线程的消息机制来进行的。例如当用户点击了某个Button,系统会向主线程发送消息,主线程的Looper从主线程消息队列中取出消息并处理,处理完当前消息,主线程Looper再去取出下一个消息。当主线程做了耗时的任务,主线程的Looper就无法从消息队列中取出新的消息,所表现出的就是程序卡顿,甚至是ANR。同理,我们在子线程往主线程发送一个消息,要是消息无法得到及时处理,那说明程序发生ANR了。思路:在子线程里向主线程发消息,如果过了固定时间后,消息仍未处理,则说明已发生ANR了当程序ANR后,我们可以通过主线程Looper拿到主线程Thread,然后通过getStackTrace拿到主线程当前的调用栈,从而定位到发生ANR的地方,定位到耗时操作
定义一个线程, 用来监测主线程
class WatchDogThread : Thread() { companion object { val MESSAGE_WATCHDOG_TIME_TICK = 0 /** * 判定Activity发生了ANR的时间,必须要小于5秒,否则等弹出ANR,可能就被用户立即杀死了。 */ val ACTIVITY_ANR_TIMEOUT = 2000 private var lastTimeTick = -1 private var timeTick = 0 } private val watchDogHandler = object : android.os.Handler() { override fun handleMessage(msg: Message) { timeTick++ timeTick %= Integer.MAX_VALUE } } override fun run() { while (true) { watchDogHandler.sendEmptyMessage(MESSAGE_WATCHDOG_TIME_TICK) try { Thread.sleep(ACTIVITY_ANR_TIMEOUT.toLong()) } catch (e: InterruptedException) { e.printStackTrace() } // 如果相等,说明过了ACTIVITY_ANR_TIMEOUT的时间后watchDogHandler仍没有处理消息,已经ANR了 if (timeTick == lastTimeTick) { throw ANRException() } else { lastTimeTick = timeTick } } }}
在Application启动监测线程
public class MyApplication extends Application { @Override public void onCreate() { new WatchDogThread().start(); super.onCreate(); } }
当监测到发生ANR时,抛出一个自定义异常
class ANRException : RuntimeException("应用程序无响应,快来改BUG啊!!") { init { val mainThread = Looper.getMainLooper().thread stackTrace = mainThread.stackTrace }}
更多相关文章
- android 下载图片到本地 sdcard
- android之AIDL跨进程通信详解 (四)AIDL中RemoteCallbackList的使
- Android异步更新UI的方式之使用Handler消息传递机制
- Android(安卓)Thread第二次Thread.start()报错的疑问
- Android异步更新UI的方式之使用Handler的post(Runnabel r)方法
- 学习笔记:Android开源库使用方法总结
- Android(安卓)开发即时聊天工具 YQ :(五) 发送消息
- Java(Android)数据结构汇总(二)-- Set(下)
- android 更新UI的两种方法