一. 内存优化
- 不要过度使用枚举,枚举占用的内存空间要比整型大。
- 适度使用静态变量、单例;
- 使用一些Android特有的数据结构,比如SparseArray和Pair等
- 适当采用软引用和弱引用
- 采用内存缓存和磁盘缓存
- 尽量采用静态内部类,这样可以避免潜在的由于内部类而导致的内存泄漏。
二. 布局优化
- 相同层级能完成的布局,推荐FrameLayout > LinearLayout > RelativeLayout
- 使用RelativeLayout代替LinearLayout来减少层级嵌套
- 布局复用,使用<include>标签重用layout
- 提高显示速度,使用<ViewStub>延迟部分View加载
- 减少层级,使用<merge>标签替换父级布局
- 尽量少使用wrap_content,因为wrap_content会增加measure计算成本
- 删除控件中无用属性,如避免重复设置background等
三.渲染优化
过度绘制是指在屏幕上的某个像素在同一帧的时间内被绘制了多次。在多层次重叠的 UI 结构中,如果不可见的 UI 也在做绘制的操作,就会导致某些像素区域被绘制了多次,从而浪费了多余的 CPU 以及 GPU 资源。
可以通过开发者选项查看是否过度绘制
开发者选项
原色:没有过度绘制
蓝色:1 次过度绘制
绿色:2 次过度绘制
粉色:3 次过度绘制
红色:4 次及以上过度绘制
优化:
- 布局上的优化,移除 XML 中非必须的背景,移除 Window 默认的背景、按需显示占位背景图片。
- 自定义View优化,使用 canvas.clipRect()来帮助系统识别那些可见的区域,只有在这个区域内才会被绘制。
- 减少页面的绘制次数;
- 减小需要绘制的区域;
- onDraw中尽量不要创建新的局部对象。 因为onDraw方法可能会被频繁调用,这样就会在一瞬间产生大量的临时对象,这不仅占用了过多的内存而且还会导致系统更加频繁gc,降低了程序的执行效率。
- onDraw方法中不要做耗时的任务,也不能执行成千上万次的循环操作,尽管每次循环都很轻量级,但是大量的循环仍然十分抢占CPU的时间片,这会造成View的绘制过程不流畅。
按照Google官方给出的性能优化典范中的标准,View的绘制频率保证60fps是最佳的,这就要求每帧绘制时间不超过16ms(16ms = 1000/60),虽然程序很难保证16ms这个时间,但是尽量降低onDraw方法中的复杂度总是切实有效的。
四. 交互优化
-
避免在主线程中做耗时操作。
Android规定,Activity如果5秒钟之内无法响应屏幕触摸事件或者键盘输入事件就会出现ANR,而BroadcastReceiver如果10秒钟之内还未执行完操作也会出现ANR。 -
ListView | RecyclerView 优化
a. 使用ViewHolder模式来提高效率。
Viewholder模式充分了ListView的视图缓存机制,避免了每次在调用getView的时候都去通过findViewById实例化数据。
b. 耗时的操作放在异步线程中。
在adapter中的某些操作需要耗费大量的时间,这个时候就要用到异步线程来进行异步就在数据。比如:现在要加载图片,此时我们需要根据url访问网络得到数据,然后将数据解析为Bitmap设置给View。
c. ListView分页加载,并在滑动时停止加载
滑动时,显示在屏幕的Item会不断的变化,如果一直加载Item,也没有必要,因此应该在停止滑动时再加载数据。
d. 图片缓存 | 数据缓存
避免在adapter中多图片或数据进行深度加工。
为ImageView设置tag来避免异步加载图片错位。如:
viewHolder.iconImg.setTag(imgUrl); // 将ImageView与url绑定
加载时通过url判断:
if (viewHolder.iconImg.getTag().equals(imgUrl)) {
//当url标记和原先设置的一样时,才设置ImageView
viewHolder.iconImg.setImageBitmap(bitmap);
}
五. 启动优化
- 解决启动闪屏
a、设置透明主题
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="android:windowFullscreen">true</item>
<item name="android:windowIsTranslucent">true</item>
</style>
b、设置闪屏页图片
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowBackground">@drawable/lunch</item> //闪屏页图片
<item name="android:windowFullscreen">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item><!--显示虚拟按键,并腾出空间-->
</style>
- Application优化
a. 立即用到 ---> 保留
b. 需主线程&不立即用到 ---> 延迟初始化
c. 不需主线程&不立即用到 ---> 子线程初始化
六. 网络优化
1. 图片加载优化
a. 根据网络状态,加载不同的图片
如:当用户处于wifi下给控件设置高清大图,当4g或者3g模式下加载正常图片,当弱网条件下加载缩略图。
b. 根据控件大小,加载不同大小的图片;
c. 图片三级缓存
2. 网络接口优化
a. 连接复用:节省连接建立时间,如开启 keep-alive。
对于Android来说默认情况下HttpURLConnection和HttpClient都开启了keep-alive。
b. 请求合并:即将多个请求合并为一个进行请求
c. 减少请求数据的大小:对于post请求,body可以做gzip压缩的,header也可以做数据压缩。返回数据的body也可以做gzip压缩,body数据体积可以缩小到原来的30%左右。
d. 数据缓存:一些不常变化的数据(如省市信息),可以缓存本地,有变更时再重新加载
七. apk瘦身
Android的apk主要有以下信息构成:
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 字节码。
resources.arsc。
记录着资源文件和资源 ID 之间的映射关系,用来根据资源 ID 寻找资源。
基于上面的组成部分,那么优化也可以从以下几个方面着手:
代码混淆。使用proGuard 代码混淆器工具,它包括压缩、优化、混淆等功能。
资源优化。比如使用 Android Lint 删除冗余资源,资源文件最少化等。
图片优化。比如利用 AAPT 工具对 PNG 格式的图片做压缩处理,降低图片色彩位数等。
避免重复功能的库。使用 WebP图片格式等。
插件化。比如功能模块放在服务器上,按需下载,可以减少安装包大小。
(部分内容参考于网络,如有不妥,请联系删除~)
网友评论