抖音字体大小设置方法安卓 抖音字体大小设置方法(11)


通过后续分析发现对于 WebViewFactoryProvider 接口的 getStatics、 getGeolocationPermission、createWebView 等多个方法的首次调用都会触发 WebViewChromiumAwInit 的 ensureChromiumStartedLocked 往主线程 post 一个耗时消息,因此我们的问题就变成了对于WebViewFactoryProvider 相关方法的调用定位 。
一种定位办法就是通过插桩的方式实现,由于 WebViewFactoryProvider 并不是应用能够直接访问到的类,因此我们对于 WebViewFactoryProvider 的调用必然是通过调用 framework 其他代码实现的,这种情况下我们需要去分析 framework 中所有对于 WebViewFactoryProvider 的调用点,然后把应用中所有对于这些调用点的调用都进行插桩,进行日志输出以进行定位 。很显然这种方式成本是比较高的,比较容易出现漏掉的情况 。
事实上对于 WebViewFactoryProvider 的情况我们可以采用一个更便捷的方式 。在前面的分析中我们知道 WebViewFactoryProvider 是一个接口,我们是通过反射的方式获得其在 Webview 应用中实现的方式获得的,因此我们完全可以通过动态代理方式生成一个 WebViewFactoryProvider 对象,去替换 WebViewFactory 中的 WebViewFactoryProvider,在生成的 WebViewFactoryProvider 类的 invoke 方法中通过方法名过滤,对于我们的白名单方法输出其调用栈 。通过这样的方式我们最终定位到触发主线程耗时逻辑的是我们的 WebView UA 的获取 。

抖音字体大小设置方法安卓 抖音字体大小设置方法


解决方案
确认到我们的耗时是由获取 WebView UA 引起的,我们可以采用本地缓存的方式解决:考虑到 WebView UA 记录的是 Webview 的版本等信息,其在绝大部分情况下是不会发生变化的,因此我们完全可以把 Webview UA 缓存在本地,后续直接从本地进行读取,并且在每次应用切到后台时,去获取一次 WebView UA 更新到本地缓存,以避免造成使用过程中的卡顿 。
缓存的方案在 Webview 升级等造成 Webview UA 发生变化的情况下可能会出现更新不及时的情况,如果对 WebView 的实时性要求非常高,我们也可以通过调用子进程 ContentProvider 的方式在子进程去获取 WebView UA,这样虽然会影响到子进程的的主线程但是不会影响到我们的前台进程 。当然这种方式由于需要启动一个子进程同时需要走完整的 Webview UA 读取,相对本地缓存的方式在读取速度方面是有明显的劣势的,对于一些对读取速度有要求的场景是不太适合的,我们可以根据实际需要采用相应的方案 。
2. 后台任务优化
前面的案例基本都是主线程相关耗时的优化,事实上除了主线程直接的耗时,后台任务的耗时也是会影响到我们的启动速度的,因为它们会抢占我们前台任务的 cpu、io 等资源,导致前台任务的执行时间变长,因此我们在优化前台耗时的同时也需要优化我们的后台任务 。一般来说后台任务的优化与具体的业务有很强的关联性,不过我们也可以整理出来一些共性的优化原则:
减少后台线程不必要的任务的执行,特别是一些重 CPU、IO 的任务;对启动阶段线程数进行收敛,防止过多的并发任务抢占主线程资源,同时也可以避免频繁的线程间调度降低并发效率 。
除了这些通用的原则,这里也介绍两个抖音中比较典型的后台任务优化的案例 。
2.1 进程启动优化
我们优化过程中除了需要关注当前进程后台线程的运行情况,也需要关注后台进程的运行情况 。目前绝大部分应用都会有 push 功能,为了减少后台耗电、避免因为占用过多内存导致进程被杀,一般情况下会把 push 相关功能放在独立的进程 。如果在启动阶段去启动 push 进程,其也会对我们的启动速度造成比较大的影响,我们尽量对 push 进程的启动去进行适当延迟,避免在启动阶段启动 。

推荐阅读