启动优化

android启动优化知识点记录


冷启动

Click Event -> IPC -> Process.start -> ActivityThread -> bindApplication -> LifeCycle -> ViewRootImpl

其中bindApplication(Application阶段):
bindApplication->attachBaseContext->install Provider->app:onCreate

其中lifecycle(Activity阶段):
Activity生命周期->ViewRootImpl View绘制

热启动

直接从后台切换到前台。

温启动

只会重走Activity的生命周期,而不会重走进程的创建,Application的创建与生命周期等。

优化方向

一般在创建进程以及之前都是无法干预的,所以优化方向就是 Application和Activity的生命周期 这个阶段

可以使用代码插桩的方式进行方法耗时统计,可参考文章【ASM插桩基础使用(Java)】

然后相关日志上传需要注意,建议使用抽样上传,不需要全量数据

entry:
onStart—->
onResume—->
onAttachedToWindow———–>
onWindowVisibilityChanged–visibility=0———->
onWindowFocusChanged(true)——->

onWindowFocusChanged只是首帧时间

如果需要算上首页接口时间,可以用getViewTreeObserver().addOnPreDrawListener()(在API 16以上可以使用addOnDrawListener)

Systrace

常规方案

1.设置Activity的windowBackground
2.第三方库懒加载,针对于一些应用启动时不需要初始化的库,可以等到用时才进行加载。
3.设置线程优先级
1)nice值,Process中定义,值越小,优先级越高,默认是THREAD_PRIORITY_DEFAUT=0,Process.setThreadPriority() 可以设置多次
2)cgroup,一种更严格的群组调度策略
4.异步
1)Thread
2)HandlerThread,自带消息循环的线程,串行执行
3)IntentService,继承自Service在内部创建HandlerThread,优先级较高,不易被系统Kill
4)AsyncTask,Android提供的工具类
5)线程池
6)Rxjava
5.线程收敛
统一内部库的线程库,区别 IO密集型任务 和 CPU密集型任务
参考https://juejin.cn/post/6844904093786308622
// 如果当前执行的任务是CPU密集型任务,则从基础线程池组件 DispatcherExecutor中获取到用于执行 CPU 密集型任务的线程池 DispatcherExecutor.getCPUExecutor().execute(YourRunable());
直接使用 new ThreadPoolExecutor()结合CPU数量自定义
// 如果当前执行的任务是IO密集型任务,则从基础线程池组件DispatcherExecutor中获取到用于执行 IO 密集型任务的线程池 DispatcherExecutor.getIOExecutor().execute(YourRunable());
直接使用 Executors.newCachedThreadPool


线程池:
newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按先进先出的顺序执行。
newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。(空闲线程可以重复利用)
newFixedThreadPool
创建一个固定数目的、可重用的线程池。
newScheduledThreadPool
创建一个定时线程池,支持定时及周期性任务执行。


6.异步启动器
1、任务Task化,启动逻辑抽象成Task(Task即对应一个个的初始化任务)。
2、根据所有任务依赖关系排序生成一个有向无环图
3、多线程按照排序后的优先级依次执行

7.延迟启动器
利用IdleHandler特性,在CPU空闲时执行,对延迟任务进行分批初始化。

启动器总结:
能异步的task我们会优先使用异步启动器在Application的onCreate方法中加载,对于不能异步的task,我们可以利用延迟启动器进行加载。如果任务可以到用时再加载,可以使用懒加载的方式。

8.inline 方法内敛

9.WebView启动优化
1)WebView首次创建比较耗时,需要预先创建WebView提前将其内核初始化。
2)使用WebView缓存池,用到WebView的时候都从缓存池中拿,注意内存泄漏问题。

10.页面数据预加载


得物篇记录
https://mp.weixin.qq.com/s/f9ng0wabLwwXNfCO00qtPQ

1.webview分段加载
2.Arouter
3.锁优化
4.优化有向无环图

以上成本都太高,门槛较高

5.x2c
6.通过hook主线程的消息队列,将页面生命周期回调和页面绘制相关的msg移动到消息队列的队头,这样就可以加快首页首帧内容展示的速度。(具体操作未知)


总结:

Application阶段:

异步启动器 初始化第三方SDK等

Acticity阶段:

利用IdleHandler,进行延迟启动第三方SDK等

通用:

1.采用facebook的redex:类重排,方法内敛(和byreX一同考虑)
2.webview缓存
3.统一内部线程池,区别 IO密集型任务 和 CPU密集型任务
4.设置线程优先级
5.xml转view