JoshWindsor 发表于 2022-6-1 08:45

性能优化小结

性能优化面试的时候经常会被问到,市面上大厂分享相关的黑科技也挺多的,可以对应去查看,这里就做个小小的总结,起码不会冷场。

工欲善其事,必先利其器。要想做好优化,首先得知道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优化

预创建WebViewWebView进程预初始化booster chromium引擎预初始化WebView秒开,分享的文章也挺多的

网络优化

开发时可以通过弱网模拟,定位需要优化的地方。可以了解下protobuf,至于是否需要全面替代json,就见仁见智了。okhttp开启缓存,网络资源进行压缩,图片加载使用占位图,列表加载使用骨架屏等。尽量避免客户端的轮询,使用服务器推送。定位耗时的接口,与后端大佬沟通链路问题。网络请求绑定页面生命周期,避免资源浪费。
页: [1]
查看完整版本: 性能优化小结