Android 性能优化面试题集锦
下述是我收录整理的 Android 面试题汇总,由于篇幅原因,在这只把性能优化部分的题目列举出来,后续还会更新其余面试题内容,大家可以关注一下我,及时知晓我更新的知识点,同时这份面试集锦的整理也花费了我很多时间,有需要的朋友可以帮忙转发分享下,点个赞~
性能优化
Android 的性能优化,主要是从以下几个方面进行优化的: 稳定(内存溢出、崩溃) 流畅(卡顿) 耗损(耗电、流量) 安装包(APK 瘦身) 影响稳定性的原因很多,比如内存使用不合理、代码异常场景考虑不周全、代码逻辑不合理等,都会对应用的稳定性造成影响。其中最常见的两个场景是:Crash 和 ANR,这两个错误将会使得程序无法使用。所以做好 Crash 全局监控,处理闪退同时把崩溃信息、异常信息收集记录起来,以便后续分析;合理使用主线程处理业务,不要在主线程中做耗时操作,防止 ANR 程序无响应发生。
(一)稳定——内存优化
(1)Memory Monitor 工具:
它是 Android Studio 自带的一个内存监视工具,它可以很好地帮助我们进行内存实时分析。通过点击 Android Studio 右下角的 Memory Monitor 标签,打开工具可以看见较浅蓝色代表 free 的内存,而深色的部分代表使用的内存从内存变换的走势图变换,可以判断关于内存的使用状态,例如当内存持续增高时,可能发生内存泄漏;当内存突然减少时,可能发生 GC 等,如下图所示。
(2)LeakCanary 工具:
LeakCanary 是 Square 公司基于 MAT 开发的一款监控 Android 内存泄漏的开源框架。其工作的原理是: 监测机制利用了 Java 的 WeakReference 和 ReferenceQueue,通过将 Activity 包装到 WeakReference 中,被 WeakReference 包装过的 Activity 对象如果被回收,该 WeakReference 引用会被放到 ReferenceQueue 中,通过监测 ReferenceQueue 里面的内容就能检查到 Activity 是否能够被回收(在 ReferenceQueue 中说明可以被回收,不存在泄漏;否则,可能存在泄漏,LeakCanary 是执行一遍 GC,若还未在 ReferenceQueue 中,就会认定为泄漏)。
如果 Activity 被认定为泄露了,就抓取内存 dump 文件(Debug.dumpHprofData);之后通过 HeapAnalyzerService.runAnalysis 进行分析内存文件分析;接着通过 HeapAnalyzer (checkForLeak—findLeakingReference---findLeakTrace)来进行内存泄漏分析。最后通过 DisplayLeakService 进行内存泄漏的展示。
(3)Android Lint 工具:
Android Lint Tool 是 Android Sutido 种集成的一个 Android 代码提示工具,它可以给你布局、代码提供非常强大的帮助。硬编码会提示以级别警告,例如:在布局文件中写了三层冗余的 LinearLayout 布局、直接在 TextView 中写要显示的文字、字体大小使用 dp 而不是 sp 为单位,就会在编辑器右边看到提示。
(二)流畅——卡顿优化
卡顿的场景通常是发生在用户交互体验最直接的方面。影响卡顿的两大因素,分别是界面绘制和数据处理。
界面绘制:主要原因是绘制的层级深、页面复杂、刷新不合理,由于这些原因导致卡顿的场景更多出现在 UI 和启动后的初始界面以及跳转到页面的绘制上。
数据处理:导致这种卡顿场景的原因是数据处理量太大,一般分为三种情况,一是数据在处理 UI 线程,二是数据处理占用 CPU 高,导致主线程拿不到时间片,三是内存增加导致 GC 频繁,从而引起卡顿。
(1)布局优化
在 Android 种系统对 View 进行测量、布局和绘制时,都是通过对 View 数的遍历来进行操作的。如果一个 View 数的高度太高就会严重影响测量、布局和绘制的速度。Google 也在其 API 文档中建议 View 高度不宜哦过 10 层。现在版本种 Google 使用 RelativeLayout 替代 LineraLayout 作为默认根布局,目的就是降低 LineraLayout 嵌套产生布局树的高度,从而提高 UI 渲染的效率。
布局复用,使用标签重用 layout; 提高显示速度,使用延迟 View 加载; 减少层级,使用标签替换父级布局; 注意使用 wrap_content,会增加 measure 计算成本; 删除控件中无用属性;
(2)绘制优化
过度绘制是指在屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的 UI 结构中,如果不可见的 UI 也在做绘制的操作,就会导致某些像素区域被绘制了多次,从而浪费了多余的 CPU 以及 GPU 资源。如何避免过度绘制?
布局上的优化。移除 XML 中非必须的背景,移除 Window 默认的背景、按需显示占位背景图片
自定义 View 优化。使用 canvas.clipRect() 帮助系统识别那些可见的区域,只有在这个区域内才会被绘制。
(3)启动优化
应用一般都有闪屏页 SplashActivity,优化闪屏页的 UI 布局,可以通过 Profile GPU Rendering 检测丢帧情况。
(三)节省——耗电优化
在 Android5.0 以前,关于应用电量消耗的测试即麻烦又不准确,而 5.0 之后 Google 专门引入了一个获取设备上电量消耗信息的 API—— Battery Historian。Battery Historian 是一款由 Google 提供的 Android 系统电量分析工具,直观地展示出手机的电量消耗过程,通过输入电量分析文件,显示消耗情况。
最后提供一些可供参考耗电优化的方法:
(1)计算优化。算法、for 循环优化、Switch..case 替代 if..else、避开浮点运算。
浮点运算:计算机里整数和小数形式就是按普通格式进行存储,例如 1024、3.1415926 等等,这个没什么特点,但是这样的数精度不高,表达也不够全面,为了能够有一种数的通用表示法,就发明了浮点数。浮点数的表示形式有点像科学计数法(.***×10),它的表示形式是 0.×10,在计算机中的形式为 . e ±),其中前面的星号代表定点小数,也就是整数部分为 0 的纯小数,后面的指数部分是定点整数。利用这样的形式就能表示出任意一个整数和小数,例如 1024 就能表示成 0.1024×10^4,也就是 .1024e+004,3.1415926 就能表示成 0.31415926×10^1,也就是 .31415926e+001,这就是浮点数。浮点数进行的运算就是浮点运算。浮点运算比常规运算更复杂,因此计算机进行浮点运算速度要比进行常规运算慢得多。
(2)避免 Wake Lock 使用不当。
Wake Lock 是一种锁的机制,主要是相对系统的休眠而言的,,只要有人拿着这个锁,系统就无法进入休眠意思就是我的程序给 CPU 加了这个锁那系统就不会休眠了,这样做的目的是为了全力配合我们程序的运行。有的情况如果不这么做就会出现一些问题,比如微信等及时通讯的心跳包会在熄屏不久后停止网络访问等问题。所以微信里面是有大量使用到了 Wake_Lock 锁。系统为了节省电量,CPU 在没有任务忙的时候就会自动进入休眠。有任务需要唤醒 CPU 高效执行的时候,就会给 CPU 加 Wake_Lock 锁。大家经常犯的错误,我们很容易去唤醒 CPU 来工作,但是很容易忘记释放 Wake_Lock。
(3)使用 Job Scheduler 管理后台任务。
在 Android 5.0 API 21 中,google 提供了一个叫做 JobScheduler API 的组件,来处理当某个时间点或者当满足某个特定的条件时执行一个任务的场景,例如当用户在夜间休息时或设备接通电源适配器连接 WiFi 启动下载更新的任务。这样可以在减少资源消耗的同时提升应用的效率。
(四)安装包——APK 瘦身
(1)安装包的组成结构
assets 文件夹。存放一些配置文件、资源文件,assets 不会自动生成对应的 ID,而是通过 AssetManager 类的接口获取。
res。res 是 resource 的缩写,这个目录存放资源文件,会自动生成对应的 ID 并映射到 .R 文件中,访问直接使用资源 ID。
META-INF。保存应用的签名信息,签名信息可以验证 APK 文件的完整性。
AndroidManifest.xml。这个文件用来描述 Android 应用的配置信息,一些组件的注册信息、可使用权限等。
classes.dex。Dalvik 字节码程序,让 Dalvik 虚拟机可执行,一般情况下,Android 应用在打包时通过 Android SDK 中的 dx 工具将 Java 字节码转换为 Dalvik 字节码。
评论