启动优化小结

启动优化

启动优化主要有两个方向:

  • 一个是从视觉上优化

    • 通过设置主题让启动窗口显示logo图,让用户从视觉上觉得app已经启动了;

    • 一般app启动后会先展示广告界面,广告界面展示的时间可以根据启动的时间来决定显示多久,避免低端机因为启动慢而导致进入主界面时间过长

      • Application.attatchBaseContext -> onWIndowFocusChanged
  • 另一个是从代码上优化

    • 减少主线程的一些耗时操作

      • 比如Application中初始化的第三方框架,可以进行延迟、异步并行加载

      • 对于有依赖关系的任务,可以通过有向无环图和拓扑排序配合线程池和JUC闭锁(CountDownLatch)进行优化

    • 对布局进行优化,减少View绘制时间

有向无环图和拓扑排序

  • 有向无环图DAG(Directed acyclic graph):是指图中的线是有方向,并且没有环形的;它通常用于表示对象之间的依赖关系

  • 拓扑排序:是根据有向无环图的特点,对图中的结点根据依赖关系排出的先后顺序,按照这个顺序可以将所有结点都经过一遍;

    • 比如我们要学一些课程,有初级的、中级的、高级的,必须要先学会初级的,才能学中级的,最后才能学高级的,根据拓扑排序安排学习顺序,就可以确保所有课程都学完
  • 拓扑排序实现思路:

    • 建立一张任务入度表,记录每个任务的入度,表示有几条线指向它,也就是表示这个任务依赖多少个其他任务才能执行

    • 建立一张任务关系依赖表,记录每个任务的出度情况,当前任务被哪些任务所依赖

    • 建立一张0入度表,表示当前任务不依赖任何其他任务,可以立刻执行

    • 先从0度表中取出任务执行,执行完之后;从关系依赖表中查找依赖它的其他任务,把这些任务的入度减1,如果减1后入度刚好为0,则进入0入度表;一次循环知道所有任务执行完成;

    • 在Android中主线程任务必须放到最后再执行,因为如果主线程先执行,其他任务就只能等待它执行完,后面的任务没办法同步进行

    • CountDownloadLatch可以保证其他依赖的任务都执行完,当前任务才继续执行

      • 基于AQS(AbstractQueuedSynchronizer)实现,通过state的值来控制线程是否继续,当依赖的线程完成时调用countdown方法,state值减1,当state值变为0时,之前调用await方法被阻塞的线程就会被唤醒继续执行
    • Process.setThreadPriority:设置线程的优先级,避免与主线程抢资源

ContentProvider初始化sdk

  • ContentProvider是在Application创建之后,调用onCreate之前进行初始化的,利用这个特性,第三方sdk可以创建一个ContentProvider并在它的onCreate方法中初始化sdk,从而避免开发者在Application中手动初始化SDK

  • 缺点:

    • ContentProvider初始化后会一直在内存中不会释放,浪费内存空间

    • ContentProvider的onCreate方法是在主线程调用,作为四大组件,创建和维护都会耗时,如果过多的第三方sdk都采用这种方式初始化,会导致接入的app启动慢,而且不好优化

    • 无法保证ContentProvider初始化的顺序,可能带来未知问题,比如在第三方sdk在ContentProvider中设置捕获全局异常,我们app也是,就可能导致我们设置的无法生效

  • jetpack中有个APP start up组件,可以将多个初始化任务合并到一个ContentProvider中以优化启动速度,支持有依赖关系的初始化任务;但是缺点就是不支持多线程执行任务

    • 引入APP startup库

    • 自定义用于初始化的类,继承自Initializer

    • 将自定义的Initializer配置到AndroidManifest中

    • App startup 会在它的ContentProvider中搜索所有的自定义初始化类并调用它们onCreate方法

猜你喜欢

转载自blog.csdn.net/guangdeshishe/article/details/129903102
今日推荐