diff --git a/blogs/Android/口水话/性能优化口水话.md b/blogs/Android/口水话/性能优化口水话.md new file mode 100644 index 0000000..23e0141 --- /dev/null +++ b/blogs/Android/口水话/性能优化口水话.md @@ -0,0 +1,41 @@ +--- +性能优化口水话 +--- + +#### 目录 + +1. 包体积优化 +2. 布局优化 + +#### 包体积优化 + +Apk 包主要分为几个部分,libs so 库、dex、res、assets、resources.arsc 以及签名和 Manifest 文件。 + +常见的代码混淆、无用资源移除、ProGuard 等基本上大家都会做的,我主要做了资源精简这一块的优化,减少了 8M 左右。 + +首先是 png 图片,这是一个比较大的优化点,因为我们的最低 API 已经是 19 了,所以完全可以用 webp 替代 png。所以最开始我是写了一个 Task 来自动遍历 res 文件夹,使用 Google 开源的 cwebp 工具来转化,但是这有一个弊端,就是无法压缩第三方库里面的资源文件,所以在后面我们使用了 Gradle 3.3 版本新增的 getAllRawAndroidResources 这个 Api 可以获取到所有的资源目录,然后在进行转化。这一操作减少了 5.7M 的包体积大小。 + +还有就是遍历 res 生成 md5 值来去除重复的图片和 drawable,减少了133kb。最后配置了 resConfig,只保留中文和英文,减少了 1.1M,还可以在 devBuild 时配置 resConfig 只保留中文简体和 xxhdpi 的资源,有助于提升打包时间。 + +这些和权限输出,我都写在一个插件里面了。 + +除此之外呢,还有一些算是激进优化手段我们并没有做。对于 libs so 库,可以选择只保留 arm64-v8a,基本上现在手机大多都是这个 CPU 架构;对于 dex 可以使用 Facebook 开源的 ReDex 进行 dex 重分包、去除行号信息等优化手段;对于 resources.arsc 可以使用微信开源的 AndResGuard 对资源路径进行混淆; + +#### 布局优化 + +布局优化老生常谈了,说说我在项目中的一些实践手段吧。 + +首先考虑布局嵌套和过度绘制。 + +在写布局的时候,考虑是否有必要写布局,如果布局比较简单,是否可以选择直接 new,比如 RecyclerView 的 ItemView 可能就只是一个 TextView,这时 new TextView 显然比解析 xml 文件效率更高。如果要写布局文件了,考虑布局的复杂性,如果比较简单,FrameLayout 就行,如果布局比较复杂,可能导致嵌套过多,这时可以使用约束布局。同时为了后期维护性,我不建议使用线性布局。有时候,我们会封装一些控件放在系统控件里面,这时候就需要考虑是否可以 merge 最外层的布局。最后就是 ViewStub 延时初始化,基本上很少用。处理布局嵌套就这些,可以通过 Layout Inspector 来查看布局层级。 + +接着是过度绘制,过度绘制可能是项目中遇到最多的了。首先记住最最重要的一点,就是在往顶层布局添加 background 时,一定要考虑是否有必要。我们的 Activity 的默认主题色是灰白色,如果 UI 图给的背景色是白色,基本上无一例外大家都会在顶层布局把 background 置为灰色,这就导致了一层过度绘制,解决办法很简单,再写一个主题即可。还有些系统控件,默认是有背景色的,可以指定 background 为 null 即可,典型的就是 AppBarLayout 了。其次呢,就是代码层面的了,能少绘制就少绘制。比如 RecyclerView 的局部刷新、还有在选中/非选中的场景下,需要注意重复点击已选中的 Item 的处理以及在本地筛选数据的情况下,利用数据缓存避免重复处理数据。过度绘制就这些,可以使用开发者工具打开过度绘制查看。 + +除了上面比较常用的,还有一些优化手段可以考虑。比如使用 AsyncLayoutInflater 异步创建 View、使用掌阅开源的 X2C,这些都是建立在解析 Layout 是 IO 过程,创建 View 是通过反射为优化基础上的。 + +最后,布局优化还不能忽略后期的维护性,比如最好不要使用 LinearLayout,布局也可以写适当的注释,可以写适当的 tools 属性利于预览,当布局代码很多时,可以使用 editor-fold 来折叠代码块。 + + + + +