然而在实际场景中,拆分出来的三个方法中的任务可能存在依赖关系导致情况变得复杂:
- onCreateBlock() 只能依赖 onCreateAsync() 内任务m依赖 onCreateSync() 会导致死锁;
- onCreateSync() 可依赖其他两个方法内的任务;
- onCreateAsync() 可依赖其他两个方法内的任务,同时可尽可能支持多条子线程任务来加快缩短所有异步任务的完成时间,这取决于当前设备的 CPU 状态
如果按照上述的逻辑来重新梳理启动任务的初始化,则需要实现一下逻辑:
- 封装 Task 支持上述三种场景的运行
- 提供线程池以运行异步任务,Handler#Post 运行同步非阻塞任务
- 以 Task 为图节点,构建一张应用依赖启动图并从头部开始初始化
- Task 运行状态支持拦截提供外部业务逻辑获取状态,打断初始化等
- 多条异步子链运行时尽可能保持同时并发
- …
希望完成上述功能,优先考虑现有轮子。于是在 github找到了 alpha 。 alpha 是一个阿里巴巴开源的,基于PERT图构建的Android异步启动框架,协助应用启动时正确执行依赖任务。集成了之后发现满足不了项目的应用场景,当时并没有很好的解决方法,迫于项目需求当晚就 clone 下了源码研究了实现,略感失落,但也找到了优化的方向。
alpha 的缺陷
- 启动节点粒度不够细
alpha 封装了 Task 类用于表示一个异步任务, 衍生出Project 及 AnchorTask 用于处理多个 task 对象构成的图结构。其外层业务只需要继承 Task 或者同个构建 Project 来编写业务依赖逻辑,理想的结构应该如下
但是如果你添加 Task 启动的时候,会收到 xxxTask cannot be cast to com.alibaba.android.alpha.Project
。 从源码层上看确实不能从一个 task 启动,缺乏灵活性。
- 无法满足同异步初始化依赖并阻塞 Application#onCreate
alpha 定位为异步启动框架。在执行启动任务时判断其是否是主线程执行,如果是则通过 handler#post
发送出去排队处理, 否则交给线程池处理。任务处理完成之后通知依赖该任务的任务进行依赖检查, 此时若依赖其的所有依赖都已完成,则启动该任务。
定义一个任务 T,其启动任务时刻为 tTStart,结束任务时刻为 tTEnd。若存在以下依赖任务,
D(异步)-> C(异步) ->B (同步)->A(同步)
则 alpha 中恒满足 tAStart < tAEnd < tBStart < tBEnd < tCStart < tCEnd < tDStart < tDEnd
。 由于同步任务时通过队列排队处理,任务的执行并不是与代码块的上下文严格同步,当 Application#onCreate() 中要求严格的代码执行同步时,如
public void onCreate(){
startInitTask() //启动上述链
code //后置代码块
}
则后置代码块会优先被执行。当tCode
为代码块执行时刻时,恒满足 tCode < txStart (x = {A,B,C,D})
尽管 alpha 中提供 AlphaManager#waitUntilFinish 用于阻塞执行线程,但是存在很大缺陷:
假如在UI线程等待,则会造成死锁。其原因在于当前执行代码处等待解锁,而只有等到所有在主线程执行的 task 执行完才可能解锁,而 task 被 post 到消息队列里面,只有当解锁之后才能执行到消息队列的 task。
- 缺乏任务执行同步支持,同异步混合链支持及调度优化
很多应用都会在 application#onCreate
前保证某些初始化任务完成之后再进入 activity
生命周期。同时,如果在进入 activity
生命周期前这块宝贵的时候可结合设备的 cpu 资源来尽可能执行一些异步初始化任务。
遗憾的是,官方上一次更新时 2 年前了,并没有好好打算支持并维护好 alpha 库。
anchors 更适合 Android 启动场景
anchors 是一个基于图结构,支持同异步依赖任务初始化 Android 启动框架。其锚点特性提供 “勾住” 依赖的功能,能灵活解决初始化过程中复杂的同步问题。参考 alpha 并改进其部分细节, 更贴合 Android 启动的场景, 同时支持优化依赖初始化流程, 选择较优的路径进行初始化。
目前已经稳定服务于我们线上项目一年多了,经过改造之后,相比 alpha
的优势
- 支持配置
anchors
等待任务链,常用于application#onCreate
前保证某些初始化任务完成之后再进入activity
生命周期回调。 - 支持主动请求阻塞等待任务,常用于任务链上的某些初始化任务需要用户逻辑确认;
- 支持同异步任务链,使你的依赖链不再局限于同步或者异步,框架灵活帮你切换调度。
如果一个任务要确保在 application#onCreate
前执行完毕,则该任务成为锚点任务,使用起来非常简单。
添加依赖
implementation ‘com.effective.android:anchors:1.1.0’
在 Application
中启动依赖图,提供 java/kotlin 两套 api 方便使用。
//java 代码
AnchorsManager.getInstance().debuggable(true)
.addAnchors(anchorYouNeed) //传递任务id设置锚点任务
.start(dependencyGraphHead); //传入依赖图头部
//kotlin code
getInstance()
.debuggable { true }
.taskFactory { TestTaskFactory() } //可选,构建依赖图可以使用工厂,
.anchors { arrayOf(“TASK_9”, “TASK_10”) } //传递任务 id 设置锚点任务
.block(“TASK_13”) { //可选,如果需要用户在某个任务结束之后进行交互,则使用 block 功能
//According to business it.smash() or it.unlock()
}
.graphics { // 可选,当使用工程时支持 dsl 构建图,sons 接受子节点
UITHREAD_TASK_A.sons(
TASK_10.sons(
TASK_11.sons(
TASK_12.sons(
TASK_13))),
TASK_20.sons(
TASK_21.sons(
TASK_22.sons(TASK_23))),
UITHREAD_TASK_B.alsoParents(TASK_22),
UITHREAD_TASK_C
)
arrayOf(UITHREAD_TASK_A)
}
.startUp()
如果你打开了 debug 模式,则可以看到整个初始化过程的详细信息,可过渡不同 TAG
来获取对应信息。
- TASK_DETAIL 任务执行信息
D/TASK_DETAIL: TASK_DETAIL
======================= task (UITHREAD_TASK_A ) =======================
| 依赖任务 :
| 是否是锚点任务 : false
| 线程信息 : main
| 开始时刻 : 1552889985401 ms
| 等待运行耗时 : 85 ms
| 运行任务耗时 : 200 ms
| 结束时刻 : 1552889985686
- ANCHOR_DETAIL 锚点任务信息
W/ANCHOR_DETAIL: anchor “TASK_100” no found !
W/ANCHOR_DETAIL: anchor “TASK_E” no found !
D/ANCHOR_DETAIL: has some anchors!( “TASK_93” )
D/ANCHOR_DETAIL: TASK_DETAIL
======================= task (TASK_93 ) =======================
| 依赖任务 : TASK_92
| 是否是锚点任务 : true
| 线程信息 : Anchors Thread #7
| 开始时刻 : 1552891353984 ms
| 等待运行耗时 : 4 ms
| 运行任务耗时 : 200 ms
| 结束时刻 : 1552891354188
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
文末
我总结了一些Android核心知识点,以及一些最新的大厂面试题、知识脑图和视频资料解析。
以后的路也希望我们能一起走下去。(谢谢大家一直以来的支持)
部分资料一览:
- 330页PDF Android学习核心笔记(内含8大板块)
-
Android学习的系统对应视频
-
Android进阶的系统对应学习资料
- Android BAT大厂面试题(有解析)
711816215559)]
-
Android学习的系统对应视频
-
Android进阶的系统对应学习资料
[外链图片转存中…(img-GK2BXoEY-1711816215560)]
- Android BAT大厂面试题(有解析)
[外链图片转存中…(img-iD8R7paT-1711816215560)]