|
1 | | -[TOC] |
2 | 1 |
|
3 | | -## 1. 绘制优化 |
4 | 2 |
|
5 | | -### 1.1 卡顿优化 |
| 3 | +### 1、 你对 APP 的启动有过研究吗? 有做过相关的启动优化吗? |
6 | 4 |
|
7 | | -#### 卡顿的根本原因 |
| 5 | +###2、 有做过相关的内存优化吗? |
8 | 6 |
|
9 | | -- 绘制任务太重,绘制一帧内容耗时太长 |
10 | | -- 主线程太忙了,导致 VSync 信号来时还没有准备好数据导致丢帧 |
| 7 | +### 3、你在项目中有没有遇见卡顿问题?是怎么排查卡顿?又是怎么优化的? |
11 | 8 |
|
12 | | -#### 主线程主要做什么 |
| 9 | +### 4、怎么保证 APP 的稳定运行? |
13 | 10 |
|
14 | | -- UI 声明周期控制 |
15 | | -- 系统事件处理 |
16 | | -- 消息处理 |
17 | | -- 界面布局 |
18 | | -- 界面绘制 |
19 | | -- 界面刷新 |
| 11 | +### 5、说说你在项目中网络优化? |
20 | 12 |
|
21 | | -处了这些以外避免将其他耗时任务放在主线程操作。 |
| 13 | +### 6、你在项目中有用过哪些存储方式? 对它们的性能有过优化吗? |
22 | 14 |
|
23 | | -#### 性能分析工具 |
| 15 | +### 7、你在项目中有做过自定义 View 吗?有对它做过什么优化? |
24 | 16 |
|
25 | | -- 卡顿检测工具 |
26 | | - - Profile GPU Rendering (不利于分析) |
27 | | - - 通过 `adb shell dumpsys gfxinfo 包名` 可以把具体时间耗时输出到日志中 |
28 | | -- TraceView |
29 | | - - Debug.startMethodTracing(Environment.getExternalStorageDirectory() + File.separator + "test.trace"); |
30 | | - - Debug.stopMethodTracing(); |
31 | | - - 直接拖动到 AS 中打开 |
32 | | -- Systrace UI 性能分析 |
| 17 | +### 8、你们项目的耗电量怎么样? 有做过优化吗? |
33 | 18 |
|
34 | | -### 1.1 布局优化 |
| 19 | +###9、有做过日志优化吗? |
35 | 20 |
|
36 | | -- 常用布局优化工具 |
37 | | - - Layout Inspector |
38 | | - - 布局层级查看 File ->Settings -> Inspections -> Android Lint |
| 21 | +###10、你们 APK 有多大?有做过 APK 体积相关的优化吗? |
39 | 22 |
|
40 | | -- 布局优化方法 |
41 | | - - 1. 减少层级 |
42 | | - - 2. Merge 使用(如果用 Merge 系统在加载布局转换为对象的时候会把 Merge 标签下的子元素加载到 Parent 中) |
43 | | - 1. 只能用在根元素使用 |
44 | | - 2. 使用 merge 来加载一个布局时,必须指定一个 Parent 并且要设置 attachToRoot(true) |
45 | | - 3. 不能在 ViewStub 中使用 Merge 标签 |
46 | | - 4. 如果代码层级确实很多可以参考将 Activity 的(id/content) 容器拿到,将 merge 添加进去。 |
47 | | - - 3. 提高显示速度 - ViewStub |
48 | | - - 4. 布局复用 - include |
49 | | -- 建议优化点 |
50 | | - - 尽量多使用 RelativeLayout ,LinearLayout ,不要使用绝对布局 |
51 | | - - 通用布局以 include 代替 |
52 | | - - 使用 merge 标签减少布局层级的嵌套 |
53 | | - - 尽量少用 wrap_content ,wrap_content 会增加布局 measure 是的计算成本,已知宽高为固定值时,不用 wrap_content. |
54 | | - - 删除控件中无用属性 |
55 | 23 |
|
56 | | -### 1.2 避免过度绘制 |
57 | 24 |
|
58 | | -- 过度绘制检测工具 |
59 | | - - Show GPU Overdraw |
60 | | -- 如何避免过度绘制 |
61 | | - - 1. 布局上的优化 |
62 | | - 1. 移除 XML 中非必需的背景,或者根据条件设置 |
63 | | - 2. 移除 Window 默认的背景 |
64 | | - 3. 按需显示占位背景图片 |
65 | | - - 2. 自定义 View 优化 |
66 | | - 1. 使用 canvas.quickreject() 判断是否和某个矩形相交。 |
67 | | - 2. 使用 canvas.clipRect 控制显示的区域 |
68 | 25 |
|
69 | | -### 1.3 启动优化 |
70 | 26 |
|
71 | | -- 1. 启动耗时监测 |
72 | | - 1. LogCat 筛选关键字:Displayed |
73 | | - 2. adb shell am start -W com.devyk.ykav_sample/.SampleActivity |
74 | | - 3. 代码打点 |
75 | | -- 2. 优化方案 |
76 | | - 1. UI 布局 - 参考布局优化 |
77 | | - 2. 启动加载逻辑优化 |
78 | | - 1. 必要且耗时: 启动初始化,考虑线程 |
79 | | - 2. 必要不耗时:首页绘制 |
80 | | - 3. 非必要耗时:异步 |
81 | | - 4. 非必要不耗时:用时加载 |
82 | 27 |
|
83 | | -### 1.4 提升动画性能 |
84 | | - |
85 | | -- 使用属性动画,别用补间动画,可以开启硬件加速。 |
86 | | - |
87 | | -### 1.5 卡顿监控方案 |
88 | | - |
89 | | -- 自定义 Looper 中的 Printer 消息处理跟消息分发差值如果大于阀值说明卡顿了。 |
90 | | - |
91 | | -### 1.7 绘制优化总结 |
92 | | - |
93 | | -优化分为以下几个过程: |
94 | | - |
95 | | -- 1. 发现问题 |
96 | | -- 2. 分析问题 |
97 | | -- 3. 找到导致问题的原因 |
98 | | -- 4. 解决问题 |
99 | | - |
100 | | -## 2. 内存优化 |
101 | | - |
102 | | -### 2.1 了解 Android 内存管理机制 |
103 | | - |
104 | | -### 2.2 了解内存分配 |
105 | | - |
106 | | -### 2.3 了解内存回收机制 |
107 | | - |
108 | | -### 2.4 优化内存有什么意义 ? |
109 | | - |
110 | | -- 1. 减少 OOM, 提高应用稳定性。 |
111 | | -- 2. 减少卡顿,提高应用流程性。 |
112 | | -- 3. 减少内存占用,提高应用后台运行时的存货率。 |
113 | | -- 4. 减少异常发生,减少代码逻辑隐患。 |
114 | | - |
115 | | -### 2.5 内存分析工具 |
116 | | - |
117 | | -- Android 自带内存检测工具 Profile |
118 | | - |
119 | | -### 2.6 内存泄漏 |
120 | | - |
121 | | -- MAT 工具分析内存泄漏 |
122 | | -- 内存泄漏监控工具: LeakCanary |
123 | | - |
124 | | -- 常见内存泄漏场景 |
125 | | - 1. 资源性对象未关闭。File 、Cursor |
126 | | - 2. 注册对象为销毁 |
127 | | - 3. 类的静态变量持有大量对象 |
128 | | - 4. 非静态内部类的静态实例 |
129 | | - 5. Handler 临时性内存泄漏 |
130 | | - 6. 容器中的对象没清理造成的内存泄漏 |
131 | | - 7. WebView |
132 | | - |
133 | | -### 2.7 优化内存空间 |
134 | | - |
135 | | -- 1. 了解对象引用 |
136 | | - |
137 | | -- 2. 减少不必要的内存开销 |
138 | | - 1. 自动装箱 |
139 | | - 2. 内存复用 |
140 | | - 3. 视图复用 |
141 | | - 4. 对象池 |
142 | | - 5. Bitmap 复用 |
143 | | - 6. 使用最优的数据结构类型 |
144 | | - 1. HashMap 与 ArrayMap 选型 |
145 | | - 1. 当对象的数目非常小 (1000 以内),但是访问特别多,或者删除和插入频率不高时可以使用 ArrayMap。 |
146 | | - 2. 当有映射容器,有映射发生,并且所有映射的容器也是 ArrayMap 时。 |
147 | | - 7. 枚举类型 |
148 | | - 1. 使用注解优化枚举 |
149 | | - |
150 | | -- 3. 图片内存优化 |
151 | | - |
152 | | - 1. 设置位图规格 options.inPreferredConfig = RGB_? |
153 | | - |
154 | | - 1. RGB_8888 32 bit |
155 | | - 2. RGB_565 16 bit |
156 | | - 1. 显示小图片 |
157 | | - 2. 小屏幕手机或者对图片要求不高时。 |
158 | | - 3. RGB_4444 |
159 | | - 1. 用于显示用户头像 |
160 | | - |
161 | | - 2. inSampleSize |
162 | | - |
163 | | - 1. 如果内存中的图片大于屏幕显示的图片大小,或者大于指定屏幕区域的大小,这个时候就需要设置 options.inSampleSize = ? (1/4) 原始图片的 1/4 大小 |
164 | | - |
165 | | - 3. inScaled , inDensity 和 inTargetDensity 结合使用效果更佳 |
166 | | - |
167 | | - ```java |
168 | | - BitmapFactory.Options options = new BitmapFactory.Options(); |
169 | | - //不分配内存大小,和不返回实际 bitmap |
170 | | - option.inJustDecodeBounds = true; |
171 | | - BitmapFactory.decodeStream(is,null,options); |
172 | | - //isScaled = true: 系统会按照现有的目标密度来重新划分目标密度 |
173 | | - options.isScaled = true; |
174 | | - //生成对应的大小 |
175 | | - options.inDensity = options.outWidth; |
176 | | - //设置缩放比--> 处理采样为原始图片的 1/4 大 |
177 | | - options.inSampleSize = 4; |
178 | | - //生成对应的大小 |
179 | | - option.inTargetDensity = dstWith*options.inSampleSize; |
180 | | - //需要分配内存大小,返回实际 bitmap |
181 | | - option.inJustDecodeBounds = false; |
182 | | - BitmapFactory.decodeStream(is,null,options); |
183 | | - ``` |
184 | | - |
185 | | - 4. inBitmap |
186 | | - |
187 | | - 如果设置属性为 true ,那么当使用了带有该 Options 参数的 decode 方法加载内容时,decode 方法会尝试重用一个已经存在的位图。 |
188 | | - |
189 | | - 5. 图片缓存 |
190 | | - |
191 | | -### 2.8 总结 |
192 | | - |
193 | | -- 1. 检查 |
194 | | - |
195 | | -- 2. 监控 |
196 | | - |
197 | | -- 3. 优化 |
198 | | - |
199 | | -## 3. 存储优化 |
200 | | - |
201 | | -- SharedPreference: 轻量级数据库,适用于保存软件配置参数(/data/data/packageName/shared_prefs)。 |
202 | | -- SQLite: 轻量级数据库,支持 SQL 语法。适用于存储数据量大比如聊天数据等。 |
203 | | -- File: 适用于存储大数据,比如 LOG 日志等,确定更新慢 |
204 | | -- ContentProvider: 数据共享 |
205 | | - |
206 | | -### 3.1 SharedPreference |
207 | | - |
208 | | -是一个简单便捷的存储方式,在 Android 应用中,常用来存储一些简单配置信息,例如保存应用中的一个开关状态和一些数据的独家属性等,适用方便,存储数据类型少。 |
209 | | - |
210 | | -优化: |
211 | | - |
212 | | -- 1. IO 性能 |
213 | | -- 2. 同步锁问题 |
214 | | - |
215 | | -多用异步操作,不要基于 SP 做跨进程操作 |
216 | | - |
217 | | -### 3.2 File |
218 | | - |
219 | | -Android 文件系统与其他平台基于磁盘的文件系统类似,文件存储对象适合于读写大量的流逝数据,如媒体文件(图片、音视频)和其他网络传输等。 |
220 | | - |
221 | | -### 3.2 SQLite |
222 | | - |
223 | | -优化建议: |
224 | | - |
225 | | -- 1. 使用 Android 系统提供的 SQLiteStatement 类来将数据插入数据库,在性能上有一定提高,也解决了 SQL 注入问题。 |
226 | | -- 2. 使用事务(beginTranscation ->setTranscationSuccessful ->endTransaction ) |
227 | | -- 3. 异步线程,写数据库统一管理 |
228 | | - |
229 | | -### 3.3 ContentProvider |
230 | | - |
231 | | -### 3.4 序列化 |
232 | | - |
233 | | -使用场景: |
234 | | - |
235 | | -- 永久性保存对象,将对象的字节序列保存到本地文件中。 |
236 | | -- 对象在网络中传递 |
237 | | -- 对象在 IPC 间传递 |
238 | | - |
239 | | -3.4.1 Serializable 与 Parcelable 选择 |
240 | | - |
241 | | -## 4. 稳定性优化 |
242 | | - |
243 | | -- Crash 捕获 |
244 | | - |
245 | | -- ANR |
246 | | - |
247 | | -- 提高后台进程存活率 |
248 | | - |
249 | | -- 应用进程优先级 oom_adj = ? |
250 | | - |
251 | | - - -17 : 系统创建的 Native 进程 |
252 | | - - -16:系统进程,在运行的过程中永远不会杀掉,如果杀掉可能会导致严重问题 |
253 | | - - -12:核心进程,系统不会杀掉这类进程 |
254 | | - - -11:正在运行的服务进程,一般不会被杀掉 |
255 | | - - 0:前台进程,指正在前台运行的应用,被杀概率不大 |
256 | | - - 1:可见进程,用户正在使用,或者有界面在显示,除非出现异常,否则系统不会杀此类进程 |
257 | | - - 2:可感知进程,虽然不在前台,但进程还在状态,系统除非到内存非常紧张才会杀掉这类进程,比如播放音乐 |
258 | | - - 3:正在备份的进程 |
259 | | - - 4:高权重进程 |
260 | | - - 5:有 Service 进程 |
261 | | - - 6:与 Home 有交互的进程,比如有桌面部件和应用正在通信,widget 小挂件之类,一般尽量避免杀掉此进程 |
262 | | - - 7:切换进程 |
263 | | - - 8:缓存进程 |
264 | | - - 9:不活跃的进程 |
265 | | - - 15:缓存进程,内存不足才会被优先杀掉 |
266 | | - - 16:最低级别进程,只有缓存的进程 |
267 | | - |
268 | | - 杀进程的规则如下: |
269 | | - |
270 | | - - -12: 被杀几率较低 |
271 | | - - 4:Activity,高权重进程 |
272 | | - - 0:不会被杀 |
273 | | - - 进程中没有任何 Activity 会被优先杀 |
274 | | - - 空进程最容易被杀 |
275 | | - |
276 | | -## 5. 耗电优化 |
277 | | - |
278 | | -### 5.1 耗电检测工具 |
279 | | - |
280 | | -- Battery Historian |
281 | | - |
282 | | -### 5.2 显示 |
283 | | - |
284 | | -- LCD 比 OLCD 更耗电 |
285 | | - |
286 | | -###5.3 网络 |
287 | | - |
288 | | -- 1. 使用WIFI 传输数据时,尽量可能增加每个包的大小(不超过 MTU) ,并降低发包的频率。 |
289 | | -- 2. 在蜂窝移动网络下,最好做到批量执行网络请求,尽量避免频繁的间隔网络请求,尽量多地保持在 Radio Standby(空闲态) 状态。 |
290 | | -- 3. 尽量在 WIFI 模式下使用数据传输。 |
291 | | -- 4. 数据解析使用 JSON 和 Protobuf |
292 | | -- 5. 压缩数据格式,比如采用 GZIP |
293 | | - |
294 | | -### 5.4 CPU |
295 | | - |
296 | | -降低使用 CPU 频率 |
297 | | - |
298 | | -### 5.5 应用常用优化方案 |
299 | | - |
300 | | -- 1. 计算优化(浮点运算比整数运算更加消耗 CPU 时间片),因此耗电也会增加,建议使用以下方式避开: |
301 | | - 1. 除法变乘法 |
302 | | - 2. 充分利用位移 |
303 | | - 3. 利用 arm neon 指令集做并行运算,需要 arm V7 以上 CPU 架构 |
304 | | -- 2. 避免 WakeLock 使用不当 |
305 | | - 1. PARTIAL_WAKE_LOCK:保持 CPU 正常运转,屏幕和键盘灯有可能会关闭 |
306 | | - 2. SCREEN_DIM_WAKE_LOCK:保持 CPU 正常运转,运行保持屏幕显示,但是会变暗,允许关闭键盘灯 |
307 | | - 3. SCREEN_BRIGHT_WAKE_LOCK:保持 CPU 运转,允许保持屏幕高亮显示,允许关闭键盘灯 |
308 | | - 4. FULL_WAKE_LOCK: 保持 CPU 运转,保持屏幕高亮显示,键盘灯也保持高亮 |
309 | | - 5. ACQUIRE_CAUSES_WAKEUP: 强制使屏幕亮起,这种锁主要用于一些必须通知用户的操作。 |
310 | | - 6. ON_AFTER_RELEASE: 当锁为释放时,保持屏幕亮起一段时间。 |
311 | | - |
312 | | -- 3. 使用 Job Scheduler |
313 | | - 1. 重要不紧急的任务,可以延迟执行,如定期数据库数据更新和上报 |
314 | | - 2. 耗电较大的任务,比如充电时才希望执行的备份数据 |
315 | | - 3. 不紧急可以不执行的网络任务,如在 wifi 环境下预加载数据 |
316 | | - 4. 可以批量执行的任务 |
317 | | - |
318 | | - |
319 | | - |
320 | | -## 6. 安装包大小优化 |
321 | | - |
322 | | -### 6. 1 分析安装包大小工具 |
323 | | - |
324 | | -- 直接使用 AS 自带工具或者反编译 APK 分析 |
325 | | - |
326 | | -### 6.2 常用优化方案 |
327 | | - |
328 | | -- 1. 代码混淆 |
329 | | - |
330 | | -- 2. 资源优化 |
331 | | - |
332 | | -- 3. 避免重复功能的库 |
333 | | -- 4. 使用 webP图片格式 |
334 | | -- 5. 插件化 |
335 | | - |
336 | | - |
337 | | - |
338 | | - |
339 | | - |
340 | | -## 启动 |
341 | | - |
342 | | - |
343 | | - |
344 | | -## 内存 |
345 | | - |
346 | | - |
347 | | - |
348 | | -## 耗电 |
349 | | - |
350 | | - |
351 | | - |
352 | | -## 稳定流畅 |
353 | | - |
354 | | - |
355 | | - |
356 | | -## 网络 |
357 | | - |
358 | | - |
359 | | - |
360 | | -## 存储 |
361 | | - |
362 | | - |
363 | | - |
364 | | -## 自定义View |
365 | | - |
366 | | - |
367 | | - |
368 | | -## 日志 |
369 | | - |
370 | | - |
371 | | - |
372 | | -##APK |
373 | | - |
374 | | - |
375 | 28 |
|
376 | 29 |
|
377 | 30 |
|
|
0 commit comments