您的位置:首页 > 汽车 > 时评 > 厦门手机网站设计公司_有没有可以免费制作ppt的app_磁力bt种子搜索_搜索网站排名

厦门手机网站设计公司_有没有可以免费制作ppt的app_磁力bt种子搜索_搜索网站排名

2025/4/27 21:57:14 来源:https://blog.csdn.net/2301_80329517/article/details/147538673  浏览:    关键词:厦门手机网站设计公司_有没有可以免费制作ppt的app_磁力bt种子搜索_搜索网站排名
厦门手机网站设计公司_有没有可以免费制作ppt的app_磁力bt种子搜索_搜索网站排名

一、ANR 基础概念与核心原理(必考题)

1. 什么是 ANR?为什么会发生 ANR?

答案要点

  • 定义:ANR(Application Not Responding)即应用无响应,是 Android 系统检测到主线程(UI 线程)长时间阻塞时触发的机制,用户会看到 “等待 / 关闭应用” 对话框18。
  • 根本原因:主线程被耗时操作(如 IO、网络请求、复杂计算)阻塞,或因锁竞争、CPU 资源不足导致无法及时处理输入事件或系统回调911。
  • 系统检测机制
    • 输入事件:5 秒未处理(如点击、滑动)513。
    • 广播接收器:前台广播 10 秒、后台广播 60 秒未完成onReceive47。
    • 服务:前台服务 20 秒、后台服务 200 秒未完成onStartCommand等生命周期方法413。
    • 内容提供者:10 秒未完成query/insert等操作513。
2. 列举 ANR 的四种场景及超时时间(高频考点)

答案要点

场景超时时间触发条件
输入事件超时5 秒用户交互(如点击、滑动)未在 5 秒内处理完成513。
前台广播超时10 秒BroadcastReceiver.onReceive执行超过 10 秒(如Context.sendOrderedBroadcast)47。
后台广播超时60 秒后台广播(如Context.startBroadcast)未在 60 秒内完成413。
前台服务超时20 秒Service.onStartCommand/onBind未在 20 秒内返回413。
后台服务超时200 秒后台服务执行超过 200 秒(Android 8.0+)413。
内容提供者超时10 秒ContentProviderquery/insert等方法未在 10 秒内完成513。

注意:不同 Android 版本可能略有差异,需强调常见标准值47。

二、ANR 日志分析与定位(技术难点)

1. 如何通过日志定位 ANR 原因?

答案要点

  • 日志获取
    • 使用adb pull /data/anr/traces.txt导出 ANR 日志67。
    • 通过adb logcat -b events -s anr实时捕获 ANR 信息6。
  • 关键字段解析
    • ANR in com.example.app:定位发生 ANR 的应用包名和组件(如 Activity)67。
    • Reason: Input dispatching timed out:明确 ANR 类型(输入事件、广播等)67。
    • 主线程堆栈
      "main" prio=5 tid=1 Blocked  
      at com.example.app.MainActivity.loadData(MainActivity.kt:45)  // 阻塞代码行  
      - waiting to lock <0x123456> (a java.lang.Object) owned by thread=10  // 锁竞争  
      
       
      • 分析state=S(阻塞状态)、waiting to lock(锁持有者)及具体代码行号79。
    • 其他线程状态
      "Thread-10" prio=5 tid=10 Holding lock  
      at com.example.app.DataManager.lockData(DataManager.kt:78)  // 持有锁的线程  
      
       
      • 检查是否有子线程长时间持有锁或占用 CPU79。

面试技巧:结合日志示例说明分析步骤,强调从Reason→主线程堆栈→其他线程状态的逻辑链67。

2. 如何区分 ANR 是应用自身问题还是系统资源不足?

答案要点

  • 应用自身问题
    • 主线程堆栈显示耗时操作(如Thread.sleep、数据库查询)911。
    • 锁竞争导致主线程等待(如synchronized块未及时释放锁)79。
  • 系统资源不足
    • 日志中CPU usage显示高负载(如user + kernel > 80%)713。
    • 内存不足导致频繁 GC 或进程被回收913。
  • 工具辅助
    • 使用adb shell top -m 10 -s cpu查看 CPU 占用,定位高负载进程79。
    • 通过 Android Studio Profiler 分析主线程耗时函数111。

三、ANR 规避与优化(实战重点)

1. 如何避免主线程阻塞?

答案要点

  • 耗时操作异步化
    • 使用Coroutine/Handler/WorkManager将网络请求、文件读写等移至后台线程110。
    • 示例:
      // 使用协程处理耗时任务  
      viewModelScope.launch {  val data = withContext(Dispatchers.IO) { fetchDataFromNetwork() }  withContext(Dispatchers.Main) { updateUI(data) }  
      }  
      
  • 优化布局与渲染
    • 减少布局嵌套,使用ViewStub延迟加载非必要视图19。
    • 避免在onDraw中创建对象,防止内存抖动29。
  • 合理使用锁
    • 缩小synchronized块范围,避免在锁内执行耗时操作19。
    • 使用ReentrantLock替代synchronized,提高锁竞争效率19。
2. BroadcastReceiver 导致 ANR 的原因及解决方案

答案要点

  • 原因
    • onReceive在主线程执行,若包含耗时操作(如网络请求、数据库写入),超过 10 秒 / 60 秒触发 ANR25。
    • 有序广播未及时调用abortBroadcast(),导致后续 Receiver 阻塞79。
  • 解决方案
    • 耗时操作转后台:通过IntentService/WorkManager处理异步任务210。
      class MyBroadcastReceiver : BroadcastReceiver() {  override fun onReceive(context: Context, intent: Intent) {  context.startService(Intent(context, MyIntentService::class.java))  }  
      }  
      
    • 限制onReceive逻辑:仅解析 Intent 或启动组件,避免复杂计算59。
3. Service 导致 ANR 的典型场景及优化

答案要点

  • 典型场景
    • 直接在Service.onStartCommand中执行文件下载、数据库批量操作等耗时任务29。
    • 前台服务未及时调用startForeground(),导致超时阈值按后台服务处理413。
  • 优化方案
    • 使用JobIntentService(继承自IntentService)自动处理异步任务并销毁服务110。
    • 示例:
      class MyJobService : JobIntentService() {  override fun onHandleWork(intent: Intent) {  // 后台线程执行耗时操作  doHeavyWork()  }  
      }  
      
    • 前台服务需在 5 秒内调用startForeground(),避免超时413。

四、ANR 面试高频问题与陷阱

1. 为什么 ANR 通常发生在主线程?子线程阻塞会触发 ANR 吗?

答案

  • 主线程职责:处理 UI 更新、输入事件、系统回调(如 Activity 生命周期、广播接收),任何阻塞都会导致界面无响应89。
  • 子线程阻塞:不会直接触发 ANR,但可能通过以下方式间接导致:
    • 子线程持有锁,主线程等待锁释放(锁竞争)79。
    • 子线程占用大量 CPU 资源,导致主线程无法抢占时间片913。
2. 如何模拟 ANR?列举至少两种方法

答案

  • 输入事件超时
    // 在Activity.onCreate中阻塞主线程  
    override fun onCreate(savedInstanceState: Bundle?) {  super.onCreate(savedInstanceState)  Thread.sleep(6000) // 超过5秒触发ANR  
    }  
    
  • 广播接收器超时
    class MyBroadcastReceiver : BroadcastReceiver() {  override fun onReceive(context: Context, intent: Intent) {  Thread.sleep(11000) // 前台广播超过10秒触发ANR  }  
    }  
    
  • 服务超时
    class MyService : Service() {  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {  Thread.sleep(21000) // 前台服务超过20秒触发ANR  return super.onStartCommand(intent, flags, startId)  }  
    }  
    
3. 如何监控线上 ANR?

答案要点

  • 工具推荐
    • 华为 AGC 性能管理:自动采集 ANR 日志,提供堆栈分析和系统资源状态13。
    • BlockCanary:开源库,监控主线程卡顿并输出堆栈信息111。
    • StrictMode:开发阶段检测主线程耗时操作(如磁盘 I/O、网络请求)111。
  • 实现自定义监控
    • 监听系统SIGQUIT信号,解析/data/anr/traces.txt文件111。
    • 通过Looper.getMainLooper().setMessageLogging监控消息队列延迟11。

扩展ANR日志使用

1. ANR 基础信息
** ANR in com.example.app (com.example.app/.MainActivity)  
PID: 12345  // 进程ID  
Reason: Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing its input events)  
ANR Details:  All threads were suspended except the debugger worker thread!  Wait queue length: 1  Wait queue head age: 5001ms  // 超时时间,超过5秒触发Input ANR  
  • 关键字段
    • Reason:明确 ANR 类型(Input/Service/Broadcast/Provider)。
    • Wait queue head age:阻塞持续时间,对应不同场景的超时阈值(见下文)。
2. 主线程(UI 线程)堆栈
"main" prio=5 tid=1 Blocked  | group="main" sCount=1 dsCount=0 obj=0x74a00000 self=0xabc123  | sysTid=12345 nice=0 cgrp=default sched=0/0 handle=0xdef456  | state=S schedstat=( 123456789 12345678 1234 ) utm=4 stm=6  at com.example.app.MainActivity.loadData(MainActivity.kt:45)  // 阻塞发生的代码行  - waiting to lock <0x123456> (a java.lang.Object) owned by thread=10  // 等待的锁对象  at android.app.ActivityThread.handleMessage(ActivityThread.java:1994)  at android.os.Handler.dispatchMessage(Handler.java:106)  at android.os.Looper.loop(Looper.java:164)  at android.app.ActivityThread.main(ActivityThread.java:6938)  
  • 分析重点
    • state=S:表示主线程处于阻塞(Sleep)状态。
    • waiting to lock:若存在锁竞争,显示被哪个线程(如thread=10)持有锁。
    • 代码行号:直接定位到阻塞发生的具体方法(如MainActivity.loadData)。
3. 其他线程状态
"Thread-10" prio=5 tid=10 Holding lock  | group="main" sCount=1 dsCount=0 obj=0x123456 self=0x ghi789  | sysTid=12346 nice=0 cgrp=default sched=0/0 handle=0x jkl012  | state=S schedstat=( 76543210 1234567 890 ) utm=2 stm=5  at com.example.app.DataManager.lockData(DataManager.kt:78)  // 持有锁的线程代码  - locked <0x123456> (a java.lang.Object)  

  • 若主线程因等待锁而阻塞,需检查其他线程是否长时间持有锁(如耗时操作未释放锁)。

不同场景 ANR 的日志分析实战

1. Input ANR:主线程阻塞在耗时操作
  • 日志特征
    • Reason包含Input dispatching timed out
    • 主线程堆栈显示在执行耗时操作(如 IO、复杂计算、未异步处理的网络请求)。
  • 示例分析
    // 主线程在执行文件读取(耗时操作未异步化)  
    at com.example.app.MainActivity.loadLargeFile(MainActivity.kt:105)  
    at com.example.app.MainActivity.onCreate(MainActivity.kt:40)  
    
  • 优化方向:将耗时操作移至子线程(如Coroutine/AsyncTask/WorkManager)。
2. BroadcastReceiver ANR:onReceive 耗时过长
  • 日志特征
    • Reason包含Timeout during broadcast handling
    • 主线程堆栈显示在BroadcastReceiver.onReceive中执行耗时操作(如数据库写入、网络请求)。
  • 特殊场景
    • 有序广播(Ordered Broadcast):若在onReceive中未及时调用abortBroadcast()或处理结果,可能导致后续 Receiver 阻塞。
    • 前台广播超时阈值 10 秒,后台 60 秒,需通过android:processIntentService异步处理。
  • 示例日志
    "main" prio=5 tid=1 Blocked  
    at com.example.app.MyBroadcastReceiver.onReceive(MyBroadcastReceiver.kt:30)  // 耗时的网络请求  
    
3. Service ANR:后台任务未异步化
  • 日志特征
    • Reason包含Timeout executing service
    • 主线程堆栈显示在Service.onStartCommand中执行耗时逻辑(如未使用IntentService或协程)。
  • 典型错误
    // 直接在Service主线程处理文件下载  
    at com.example.app.DownloadService.onStartCommand(DownloadService.kt:55)  
    
  • 优化方案:使用JobIntentServiceWorkManager处理异步任务。
4. 锁竞争导致的 ANR
  • 日志特征
    • 主线程状态为waiting to lock,指向某个被其他线程持有的锁(如synchronized对象)。
    • 持有锁的线程可能在执行耗时操作(如死锁、长耗时同步块)。
  • 示例分析
    // 主线程等待线程10释放锁  
    "main" waiting to lock <0x123456> (owned by thread=10)  
    "Thread-10" holding lock <0x123456> at com.example.app.DataManager.lockData(...)  
    
  • 解决方案:缩小同步块范围,避免在锁内执行耗时操作。

ANR 日志分析的核心步骤(面试高频考点)

  1. 定位 ANR 类型:通过Reason字段确定是 Input/Service/Broadcast 等类型。
  2. 提取主线程堆栈:找到阻塞发生的具体方法(关注代码行号和锁信息)。
  3. 检查超时阈值:对比日志中的Wait queue head age是否超过对应场景的阈值(如 5 秒、10 秒)。
  4. 分析其他线程:查看是否有子线程持有锁、长时间占用 CPU 或阻塞主线程。
  5. 结合代码逻辑:确认阻塞是否由耗时操作(IO / 网络 / 复杂 UI)、未异步化任务或锁竞争导致。

实战工具与技巧

  1. adb 命令辅助
    • adb shell dumpsys activity activities | grep mResumedActivity:查看当前卡顿的 Activity。
    • adb shell top -m 10 -s cpu:定位 CPU 占用高的进程,辅助判断是否因 CPU 繁忙导致主线程阻塞。
  2. Android Studio Profiler
    • 通过 CPU Profiler 查看主线程在 ANR 前后的函数调用耗时,定位耗时方法。
  3. 避免 ANR 的最佳实践
    • 主线程仅处理 UI 更新,耗时操作通过Coroutine/Handler/WorkManager异步化。
    • 限制BroadcastReceiver.onReceive执行时间(10 秒内结束,复杂逻辑启动 Service)。
    • 避免在onCreate/onResume等生命周期中执行耗时初始化操作。

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com