Skip to content

Commit b502a9e

Browse files
author
DevYK
committed
add 容器面试题和核心源码解析
1 parent 1c84cdf commit b502a9e

27 files changed

Lines changed: 4186 additions & 418 deletions

.DS_Store

0 Bytes
Binary file not shown.
1.13 KB
Binary file not shown.

性能优化/Android 平台性能优化总结.md

Lines changed: 581 additions & 9 deletions
Large diffs are not rendered by default.

性能优化/性能优化总结.md

Lines changed: 10 additions & 357 deletions
Original file line numberDiff line numberDiff line change
@@ -1,377 +1,30 @@
1-
[TOC]
21

3-
## 1. 绘制优化
42

5-
### 1.1 卡顿优化
3+
### 1、 你对 APP 的启动有过研究吗? 有做过相关的启动优化吗?
64

7-
#### 卡顿的根本原因
5+
###2、 有做过相关的内存优化吗?
86

9-
- 绘制任务太重,绘制一帧内容耗时太长
10-
- 主线程太忙了,导致 VSync 信号来时还没有准备好数据导致丢帧
7+
### 3、你在项目中有没有遇见卡顿问题?是怎么排查卡顿?又是怎么优化的?
118

12-
#### 主线程主要做什么
9+
### 4、怎么保证 APP 的稳定运行?
1310

14-
- UI 声明周期控制
15-
- 系统事件处理
16-
- 消息处理
17-
- 界面布局
18-
- 界面绘制
19-
- 界面刷新
11+
### 5、说说你在项目中网络优化?
2012

21-
处了这些以外避免将其他耗时任务放在主线程操作。
13+
### 6、你在项目中有用过哪些存储方式? 对它们的性能有过优化吗?
2214

23-
#### 性能分析工具
15+
### 7、你在项目中有做过自定义 View 吗?有对它做过什么优化?
2416

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、你们项目的耗电量怎么样? 有做过优化吗?
3318

34-
### 1.1 布局优化
19+
###9、有做过日志优化吗?
3520

36-
- 常用布局优化工具
37-
- Layout Inspector
38-
- 布局层级查看 File ->Settings -> Inspections -> Android Lint
21+
###10、你们 APK 有多大?有做过 APK 体积相关的优化吗?
3922

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-
- 删除控件中无用属性
5523

56-
### 1.2 避免过度绘制
5724

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 控制显示的区域
6825

69-
### 1.3 启动优化
7026

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. 非必要不耗时:用时加载
8227

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 SerializableParcelable 选择
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-
- 4Activity,高权重进程
272-
- 0:不会被杀
273-
- 进程中没有任何 Activity 会被优先杀
274-
- 空进程最容易被杀
275-
276-
## 5. 耗电优化
277-
278-
### 5.1 耗电检测工具
279-
280-
- Battery Historian
281-
282-
### 5.2 显示
283-
284-
- LCDOLCD 更耗电
285-
286-
###5.3 网络
287-
288-
- 1. 使用WIFI 传输数据时,尽量可能增加每个包的大小(不超过 MTU) ,并降低发包的频率。
289-
- 2. 在蜂窝移动网络下,最好做到批量执行网络请求,尽量避免频繁的间隔网络请求,尽量多地保持在 Radio Standby(空闲态) 状态。
290-
- 3. 尽量在 WIFI 模式下使用数据传输。
291-
- 4. 数据解析使用 JSONProtobuf
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-
![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200326201314.png)
343-
344-
## 内存
345-
346-
![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200326201336.png)
347-
348-
## 耗电
349-
350-
![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200326201350.png)
351-
352-
## 稳定流畅
353-
354-
![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200326201413.png)
355-
356-
## 网络
357-
358-
![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200326201427.png)
359-
360-
## 存储
361-
362-
![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200326201449.png)
363-
364-
## 自定义View
365-
366-
![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200326201459.png)
367-
368-
## 日志
369-
370-
![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200326201529.png)
371-
372-
##APK
373-
374-
![](https://devyk.oss-cn-qingdao.aliyuncs.com/blog/20200326201543.png)
37528

37629

37730

362 KB
Loading
349 KB
Loading

文章图片引用/volatile.png

176 KB
Loading
88.9 KB
Loading
11 MB
Loading

文章图片引用/慕课-1.gif

53.2 KB
Loading

0 commit comments

Comments
 (0)