工欲善其事,必先利其器。要想做好优化,首先得知道APP线上的各种数据,不管是自己撸还是接入其它家开源的,先得有个数。
-
启动优化
SDK的初始化说的比较多的就是异步加载,懒加载。异步加载的话将一些非主线程初始化的任务通过线程池,CountDownLatch计数,或者引入有向无环图处理;懒加载将非核心需要在主线程初始化的任务Idle执行。
那还有一些so包的初始化,可以配合包体积优化,做成动态下发,在对应的业务场景做初始化。现在很多框架包扩一些知名的都喜欢在自己的ContentProvider中做初始化,这一部分比较恶心,可以在Manifest中写同名的ContentProvider指定其enable为false,阻止其初始化,然后在业务中自行调用init方法。之前项目中就引入了Facebook的SDK做登录功能,结果发现其init方法太占资源,毕竟我只需要一个登录功能,通过这个方案将其初始化时机放到登录页,毕竟对于绝大部分用户来说登录了一次之后有token续期机制的存在无需再执行登录相关逻辑。
还有就是MainActivity中其它子Fragment懒加载,默认肯定只显示MainFragment。这里可以将MainFragment的json数据做持久化处理,在Splash闪屏页提前读取出来,首次加载是否需要拉取最新的接口数据,这其实也是个业务问题,可以先展示退出前保存下来的json数据再调接口拉数据。对于MainFragment来说,其绘制耗时也是可以优化一些的,老生常谈的减少层级、移除不必要的背景、ViewStub等,还有AsyncLayoutInflater提前异步加载首页View。
-
包体积优化
- 混淆,Lint去除无用资源,图片压缩、使用WebP、非必要图片网络化。
- 非核心资源文件动态下发,resConfigs过滤多语言。
- so包删除多平台只需支持armeabi-v7a,非核心so包压缩、动态下发。
- ReDex去除Dex文件debug信息及行号信息。
- ReDex分包优化,尽量将有调用关系的class放到同一个dex。
- 引入booster,资源索引内联。
-
内存优化
- LeakCanary监控内存泄漏,但不适用于线上。
- debug下推行StrictMode严格模式,查看内存泄漏。
- 图片处理,用框架的话基本没啥问题,去除透明通道,压缩到target view大小。
- 大对象复用,避免频繁创建对象,资源即时关闭。
- 开启多进程,比如WebView、Download单独开启进程。
- 多线程管理,使用线程池和相关的框架,Rxjava、Flow等。
-
页面优化
核心页面体验优化,一部分可以按MainActivity的思路来,子页面懒加载。部分文案也可以由上级页面带入,再比如播放页面播放器做秒开,其数据肯定也是由上级页面带入。其它比较多的就是耗时逻辑异步处理和懒加载,RecyclerView的优化以及骨架屏。
RecyclerView的优化:
- 如果Item高度是固定的话,设置setHasFixedSize(true)来避免requestLayout浪费资源。
- 在onScrollStateChanged()停止滑动的时候做分页处理,addOnScrollListener()滚动时会频繁计算是否滑动到底部。
- 通过RecycleView.setItemViewCacheSize(size)加大RecyclerView的缓存,用空间换时间来提高滚动的流畅性。
- 使用diffutil进行局部刷新,少用全局刷新。
- 预初始化首屏ViewHolder。
-
WebView优化
- 预创建WebView
- WebView进程预初始化
- booster chromium引擎预初始化
- WebView秒开,分享的文章也挺多的
-
网络优化
- 开发时可以通过弱网模拟,定位需要优化的地方。
- 可以了解下protobuf,至于是否需要全面替代json,就见仁见智了。
- okhttp开启缓存,网络资源进行压缩,图片加载使用占位图,列表加载使用骨架屏等。
- 尽量避免客户端的轮询,使用服务器推送。
- 定位耗时的接口,与后端大佬沟通链路问题。
- 网络请求绑定页面生命周期,避免资源浪费。
网友评论