Android异常处理与性能优化核心指南
1. Android异常与性能优化面试核心要点解析作为一名有五年Android开发经验的面试官我经常在技术面中考察候选人对异常处理和性能优化的理解。这两个主题看似基础却能真实反映开发者的实战经验和系统思维。让我们先从一个最常见的异常类型开始——ANRApplication Not Responding。1.1 ANR异常深度剖析ANR的本质是系统对应用响应能力的监控机制。当主线程被阻塞超过阈值时系统会弹出应用无响应的对话框。这个机制背后涉及三个关键监控点Activity响应超时5秒阈值按键或触摸事件BroadcastReceiver处理超时前台广播10秒后台广播60秒Service启动超时前台服务20秒后台服务200秒在实际项目中我遇到过最典型的ANR场景是// 错误示例主线程执行网络请求 Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 同步网络请求4.0后已禁止 String data HttpUtils.get(http://api.example.com/data); textView.setText(data); }1.2 性能优化关键指标除了ANR性能优化需要关注以下核心指标指标类型检测工具优化目标值启动时间ADB命令/Systrace冷启动1.5秒内存占用Android Profiler堆内存最大限制80%帧率稳定性GPU Rendering模式16ms/帧(60FPS)电量消耗Battery Historian后台耗电1%/小时经验提示在面试中常被问到的性能优化死亡问题是你的应用卡顿是怎么定位和解决的 建议准备具体案例。2. 异常处理实战技巧2.1 常见异常类型及处理方案Android开发中除了ANR还需要重点掌握这些异常OOMOutOfMemoryError典型场景Bitmap未回收、内存泄漏解决方案// 正确加载大图示例 val options BitmapFactory.Options().apply { inJustDecodeBounds true } BitmapFactory.decodeFile(path, options) options.inSampleSize calculateInSampleSize(options, reqWidth, reqHeight) options.inJustDecodeBounds false return BitmapFactory.decodeFile(path, options)Crash未捕获异常建议实现全局异常捕获Thread.setDefaultUncaughtExceptionHandler { thread, ex - // 1. 记录崩溃日志 logCrash(ex) // 2. 上传到服务器 uploadCrashData(ex) // 3. 优雅退出 Process.killProcess(Process.myPid()) }2.2 内存泄漏排查手册通过LeakCanary检测到的常见泄漏场景静态Context引用// 错误示例 public class AppUtils { private static Context sContext; // 可能泄漏Activity }Handler延迟消息// 正确做法 private val handler object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { // 处理消息 } } override fun onDestroy() { handler.removeCallbacksAndMessages(null) super.onDestroy() }匿名内部类持有外部引用// 推荐改用静态内部类弱引用 private static class MyRunnable implements Runnable { private final WeakReferenceActivity activityRef; MyRunnable(Activity activity) { this.activityRef new WeakReference(activity); } Override public void run() { Activity activity activityRef.get(); if (activity ! null) { // 操作activity } } }3. 性能优化高阶策略3.1 启动速度优化三板斧冷启动优化方案延迟初始化将非必要组件放到后台线程初始化// Application中优化示例 override fun onCreate() { super.onCreate() val startupTask StartupTask().apply { addTask(::initAnalytics) // 非关键任务 addTask(::initPushService) } startupTask.start() }布局优化技巧使用ConstraintLayout减少嵌套层级视图延迟加载ViewStub android:idid/stub_ads android:layoutlayout/ads_layout android:inflatedIdid/ads_container /Multidex预加载优化android { dexOptions { preDexLibraries true javaMaxHeapSize 4g } }3.2 内存优化实战对象池技术public class BitmapPool { private static final int MAX_SIZE 10; private static QueueBitmap pool new LinkedList(); public static Bitmap getBitmap(int width, int height) { Bitmap bitmap pool.poll(); if (bitmap null || bitmap.isRecycled()) { return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); } return bitmap; } public static void recycle(Bitmap bitmap) { if (pool.size() MAX_SIZE) { pool.offer(bitmap); } else { bitmap.recycle(); } } }Native内存监控adb shell dumpsys meminfo package_name -d4. 面试高频问题解析4.1 ANR相关八股文ANR触发条件有哪些主线程5秒无响应UI事件BroadcastReceiver未在10秒前台/60秒后台内完成Service未在20秒前台/200秒后台内完成启动如何分析ANR日志获取traces.txtadb pull /data/anr/traces.txt关键信息主线程堆栈blocked状态waiting锁信息4.2 性能优化必问题如何检测内存泄漏工具组合Android ProfilerLeakCanaryMATMemory Analyzer Tool列表卡顿如何优化优化方案// RecyclerView优化示例 recyclerView.setHasFixedSize(true) recyclerView.setItemViewCacheSize(20) recyclerView.setDrawingCacheEnabled(true) recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH)如何优化过度绘制调试命令adb shell setprop debug.hwui.overdraw show优化目标控制在2x蓝色以内5. 工具链使用技巧5.1 Android Profiler深度用法CPU Profiler采样配置推荐配置采样间隔1ms缓冲大小8MB记录Java/Kotlin和Native调用内存快照分析技巧过滤关键对象Activity实例数Fragment实例数Bitmap总大小5.2 Systrace实战指南关键参数解析# 自定义标签示例 Trace.beginSection(loadImage) try { // 耗时操作 } finally { Trace.endSection() }帧率分析要点重点关注Choreographer#doFrameUI Thread的long frame渲染线程的drawing时间6. 进阶优化方案6.1 启动阶段任务调度有向无环图调度class StartupTask { private val taskGraph mutableMapOfClassout Task, MutableListClassout Task() fun addTask(task: Classout Task, dependsOn: ListClassout Task emptyList()) { taskGraph.getOrPut(task) { mutableListOf() } dependsOn.forEach { dependency - taskGraph.getOrPut(dependency) { mutableListOf() }.add(task) } } fun start() { // 拓扑排序执行任务 } }多进程初始化service android:name.InitializationService android:process:initialization /6.2 存储IO优化SharedPreferences优化使用apply()替代commit()大文件拆分存储考虑迁移到DataStore数据库优化技巧// SQLite优化示例 db.beginTransactionNonExclusive(); try { // 批量操作 db.setTransactionSuccessful(); } finally { db.endTransaction(); }在真实的面试场景中我建议候选人准备1-2个自己解决过的具体性能问题案例。比如在我们电商App的商品详情页通过将图片加载策略从直接加载改为懒加载预加载列表滚动FPS从45提升到了58具体实现方案是... 这种有数据支撑的实战经验往往比理论回答更有说服力。