Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019-03-19:ANR 出现的场景以及解决方案? #8

Open
Moosphan opened this issue Mar 19, 2019 · 12 comments
Open

2019-03-19:ANR 出现的场景以及解决方案? #8

Moosphan opened this issue Mar 19, 2019 · 12 comments

Comments

@Moosphan
Copy link
Owner

No description provided.

@Moosphan Moosphan added the underway the daily question is solving now label Mar 19, 2019
@Ssuiyingsen
Copy link

Android系统中,AMS和WMS会检测App的响应时间,如果App在特定时间无法相应屏幕触摸或键盘输入时间,或者特定事件没有处理完毕,就会出现ANR。
例如键盘输入事件和触摸事件超过五秒就会GG
前台广播10秒没有完成 后台60秒吧
服务前台20秒 后台200秒
解决笼统一下尽量使用子线程,避免死锁的出现,使用子线程来处理耗时操作或阻塞任务。
还有就是服务内容提供者吧尽量不要执行太长时间的任务。

@Moosphan
Copy link
Owner Author

在Android中,应用的响应性被活动管理器(Activity Manager)和窗口管理器(Window Manager)这两个系统服务所监视。当用户触发了输入事件(如键盘输入,点击按钮等),如果应用5秒内没有响应用户的输入事件,那么,Android会认为该应用无响应,便弹出ANR对话框。而弹出ANR异常,也主要是为了提升用户体验。

解决方案是对于耗时的操作,比如访问网络、访问数据库等操作,需要开辟子线程,在子线程处理耗时的操作,主线程主要实现UI的操作

@Moosphan Moosphan added finished and removed underway the daily question is solving now labels Mar 20, 2019
@Alex-Cin
Copy link

我遇到过一个实际的场景, ContentResover 拿数据的时候是串行的, 看一下 binder 相关的东西, 论证一下;
在UI线程直接用解析者拿数据, 就有可能造成 ANR;

@MrSimpleX
Copy link

我觉得主要是Android中View不是线程安全的,为了保证线程安全和性能就弄了一个单线程的模型,即UI线程,来做绘制的一些操作。所有的UI线程的绘制必须在16ms内完成(保证60帧运行),所以Android里面会存在ANR的提示来保证这个原则。

@sukaidev
Copy link

我觉得主要是Android中View不是线程安全的,为了保证线程安全和性能就弄了一个单线程的模型,即UI线程,来做绘制的一些操作。所有的UI线程的绘制必须在16ms内完成(保证60帧运行),所以Android里面会存在ANR的提示来保证这个原则。

你前面说的是对的,不过跟Anr无关。ANR本质是个检测工具,用来提示用户和开发者App主线程中某个操作耗时太久并长时间未返回,这是android官方对App主线程性能的限制。

@RedDargon
Copy link

在主线程进行耗时操作,导致用户的操作没得到及时的响应 就会报出 Application Not Response 的问题 即ANR 。
这种情况往往涉及到四大组件,四大组件都是运行在主线程上的。各个组件的耗时时长不同。大概是在activity是五秒 ,广播是十秒 ,service是20秒 无响应 就会报错。
解决方法 即不要在主线程做耗时操作咯,异步处理耗时操作。

@chenqi5256969
Copy link

出现的原因:ui线程响应超时,出现超时的原因可能是ui线程发生阻塞不能及时处理当前事件,超过5s。
在BroadcastReceiver执行了耗时操作,超过10s没处理完成。

@xinyu618
Copy link

场景
1、触摸无响应5s
2、BroadCastReciver 前台处理超过10s 后台超过60s
3、Server 前台处理超过20s 后台超过200s

ANR出现的类型有两种
1、主线程耗时导致
2、CPU、内存、IO 占用过高资源耗尽(其他进程也可以导致)

如何避免
1、不要在主线程中做耗时的操作
2、避免CPU占用过高,简化方法,减少执行时间
3、避免内存占用过高,防止内存泄漏

@huazidev
Copy link

推荐看下官方 ANR 文档:
https://developer.android.com/topic/performance/vitals/anr?hl=zh-cn

ANR 出现的场景

  1. 应用在主线程上非常缓慢地执行涉及 I/O 的操作。
  2. 应用在主线程上进行长时间的计算。
  3. 主线程在对另一个进程进行同步 binder 调用,而后者需要很长时间才能返回。
  4. 主线程处于阻塞状态,为发生在另一个线程上的长操作等待同步的块。
  5. 主线程在进程中或通过 binder 调用与另一个线程之间发生死锁。主线程不只是在等待长操作执行完毕,而且处于死锁状态。
  6. 执行速度缓慢的广播接收器。

解决方式:

首先,通过各种方式定位问题

  • 使用 StrictMode 有助于开发应用时发现主线程上的意外 I/O 操作
  • 启用后台 ANR 对话框,只有在设备的开发者选项中启用了显示所有 ANR 时,Android 才会针对花费过长时间处理广播消息的应用显示 ANR 对话框
  • 使用 TraceView 在查看用例时获取正在运行的应用的跟踪信息,并找出主线程繁忙的位置
  • 通过 ANR 日志定位问题

解决问题

  1. 将执行速度缓慢的代码放到子线程处理, 比如耗时的计算
  2. 主线程上耗时的 I/O 放到子线程处理
  3. 查看对主线程所需资源持有的锁,将持有锁的时间降到最少,或者评估应用是否需要持有锁。如果使用锁来确定何时根据工作线程的处理情况来更新界面,请使用 onProgressUpdate() 和 onPostExecute() 之类的机制在工作线程和主线程之间进行通信。
  4. 对于 BroadcastReceiver 的 onReceive() 方法执行长时间运行的操作导致的 ANR, 可以将长时间运行的操作移至 IntentService。

@mlinqirong
Copy link

在UI线程执行耗时的操作会导致ANR
Activity 5秒 广播10秒 服务20秒
内存 CPU 占用多过也会导致ANR
解决方法
耗时操作不要在UI线程中执行
避免过多的占用内存 防止内存泄漏

@AndroidJiang
Copy link

  • Service Timeout:比如前台服务在20s内未执行完成,后台服务Timeout时间是前台服务的10倍,200s;
  • BroadcastQueue Timeout:比如前台广播在10s内未执行完成,后台60s;
  • ContentProvider Timeout:内容提供者,在publish过超时10s;
  • InputDispatching Timeout: 输入事件分发超时5s,包括按键和触摸事件。

@luckilyyg
Copy link

luckilyyg commented Mar 11, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests