老铁们,大家好,相信还有很多朋友对于anchors是什麼意思和一个更贴近 android 场景的启动框架 | Anchors的相关问题不太懂,没关系,今天就由我来为大家分享分享anchors是什麼意思以及一个更贴近 android 场景的启动框架 | Anchors的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!
一年前多,想找一个适合项目的Android启动任务框架时,找到了alpha。alpha是一个阿里巴巴开源的,基于PERT图构建的Android异步启动框架,协助应用启动时正确执行依赖任务。集成了之后发现满足不了项目的应用场景,当时并没有很好的解决方法,迫于项目需求当晚就clone下了源码研究了实现,略感失落,但也找到了优化的方向。
alpha封装了Task类用于表示一个异步任务,衍生出Project及AnchorTask用于处理多个task对象构成的图结构。其外层业务只需要继承Task或者同个构建Project来编写业务依赖逻辑,理想的结构应该如下
但是如果你添加Task启动的时候,会收到xxxTaskcannotbecasttocom.alibaba.android.alpha.Project。从源码层上看确实不能从一个task启动,缺乏灵活性。
2.无法满足同异步初始化依赖并阻塞Application#onCreate
alpha定位为异步启动框架。在执行启动任务时判断其是否是主线程执行,如果是则通过handler#post发送出去排队处理,否则交给线程池处理。任务处理完成之后通知依赖该任务的任务进行依赖检查,此时若依赖其的所有依赖都已完成,则启动该任务。
定义一个任务T,其启动任务时刻为tTStart,结束任务时刻为tTEnd。若存在以下依赖任务,
D(异步)->C(异步)->B(同步)->A(同步)
则alpha中恒满足tAStart<tAEnd<tBStart<tBEnd<tCStart<tCEnd<tDStart<tDEnd。
由于同步任务时通过队列排队处理,任务的执行并不是与代码块的上下文严格同步,当Application#onCreate()中要求严格的代码执行同步时,如
则后置代码块会优先被执行。当tCode为代码块执行时刻时,恒满足tCode<txStart(x={A,B,C,D})
尽管alpha中提供AlphaManager#waitUntilFinish用于阻塞执行线程,但是存在很大缺陷:
假如在UI线程等待,则会造成死锁。其原因在于当前执行代码处等待解锁,而只有等到所有在主线程执行的task执行完才可能解锁,而task被post到消息队列里面,只有当解锁之后才能执行到消息队列的task。
3.缺乏任务执行同步支持,同异步混合链支持及调度优化
很多应用都会在application#onCreate前保证某些初始化任务完成之后再进入activity生命周期。
同时,如果在进入activity生命周期前这块宝贵的时候可结合设备的cpu资源来尽可能执行一些异步初始化任务。
遗憾的是,官方上一次更新时2年前了,并没有好好打算支持并维护好alpha库。
anchors是一个基于图结构,支持同异步依赖任务初始化Android启动框架。其锚点特性提供"勾住"依赖的功能,能灵活解决初始化过程中复杂的同步问题。参考alpha并改进其部分细节,更贴合Android启动的场景,同时支持优化依赖初始化流程,选择较优的路径进行初始化。
目前已经稳定服务于我们线上项目一年多了,经过改造之后,相比alpha的优势
如果一个任务要确保在application#onCreate前执行完毕,则该任务成为锚点任务,使用起来非常简单。
implementation'com.effective.android:anchors:1.1.0'
在Application中启动依赖图,提供java/kotlin两套api方便使用。
//java代码\nAnchorsManager.getInstance().debuggable(true)\n.addAnchors(anchorYouNeed)//传递任务id设置锚点任务\n.start(dependencyGraphHead);//传入依赖图头部\n\n//kotlincode\ngetInstance()\n.debuggable{true}\n.taskFactory{TestTaskFactory()}//可选,构建依赖图可以使用工厂,\n.anchors{arrayOf("TASK_9","TASK_10")}//传递任务id设置锚点任务\n.block("TASK_13"){\t\t\t//可选,如果需要用户在某个任务结束之后进行交互,则使用block功能\n//Accordingtobusinessit.smash()orit.unlock()\n}\n.graphics{\t\t\t\t\t\t\t//可选,当使用工程时支持dsl构建图,sons接受子节点\nUITHREAD_TASK_A.sons(\nTASK_10.sons(\nTASK_11.sons(\nTASK_12.sons(\nTASK_13))),\nTASK_20.sons(\nTASK_21.sons(\nTASK_22.sons(TASK_23))),\n\nUITHREAD_TASK_B.alsoParents(TASK_22),\n\nUITHREAD_TASK_C\n)\narrayOf(UITHREAD_TASK_A)\n}\n.startUp()
如果你打开了debug模式,则可以看到整个初始化过程的详细信息,可过渡不同TAG来获取对应信息。
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_9_start(1552890473721)-->TASK_90-->TASK_91-->PROJECT_9_end(1552890473721)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_9_start(1552890473721)-->TASK_90-->TASK_92-->TASK_93-->PROJECT_9_end(1552890473721)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_8_start(1552890473721)-->TASK_80-->TASK_81-->PROJECT_8_end(1552890473721)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_8_start(1552890473721)-->TASK_80-->TASK_82-->TASK_83-->PROJECT_8_end(1552890473721)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_7_start(1552890473720)-->TASK_70-->TASK_71-->PROJECT_7_end(1552890473720)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_7_start(1552890473720)-->TASK_70-->TASK_72-->TASK_73-->PROJECT_7_end(1552890473720)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_6_start(1552890473720)-->TASK_60-->TASK_61-->PROJECT_6_end(1552890473720)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_6_start(1552890473720)-->TASK_60-->TASK_62-->TASK_63-->PROJECT_6_end(1552890473720)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_5_start(1552890473720)-->TASK_50-->TASK_51-->PROJECT_5_end(1552890473720)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_5_start(1552890473720)-->TASK_50-->TASK_52-->TASK_53-->PROJECT_5_end(1552890473720)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_4_start(1552890473720)-->TASK_40-->TASK_41-->TASK_42-->TASK_43-->PROJECT_4_end(1552890473720)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_3_start(1552890473720)-->TASK_30-->TASK_31-->TASK_32-->TASK_33-->PROJECT_3_end(1552890473720)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_2_start(1552890473719)-->TASK_20-->TASK_21-->TASK_22-->TASK_23-->PROJECT_2_end(1552890473719)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->PROJECT_1_start(1552890473719)-->TASK_10-->TASK_11-->TASK_12-->TASK_13-->PROJECT_1_end(1552890473719)
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->UITHREAD_TASK_B
D/DEPENDENCE_DETAIL:UITHREAD_TASK_A-->UITHREAD_TASK_C
有使用锚点和使用锚点场景下,针对每个依赖任务做Trace追踪,可以通过pythonsystrace.py来输出trace.html进行时间分析。
依赖图中有着一条UITHREAD_TASK_A->TASK_90->TASK_92->Task_93依赖。假设我们的这条依赖路径是后续业务的前置条件,则我们需要等待该业务完成后再进行自身的业务代码。如果不是则我们不关系他们的结束时机。在使用锚点功能时,我们勾住TASK_93,则从始端到该锚点的优先级将被提升。从上图可以看到执行该依赖链的时间缩短了。
anchors项目同时提供了核心的Sample场景进行演示。
如某初始化链中间节点需要等待响应例子中,业务逻辑可决定是否终止链继续初始化等,如下点击继续执行。
D/LOCK_DETAIL:main-unlock(TASK_10)\nD/LOCK_DETAIL:Continuethetaskchain...\nD/Anchors:TASK_10_waiter--onFinish--\nD/TASK_DETAIL:TASK_DETAIL\n\n=======================task(TASK_10_waiter)=======================\n|依赖任务:\n|是否是锚点任务:false\n|线程信息:AnchorsThread#10\n|开始时刻:1595319503047ms\n|等待运行耗时:1ms\n|运行任务耗时:3653ms\n|结束时刻:1595319506701\n==============================================\nD/Anchors:TASK_10_waiter--onRelease--
anchors框架自由度非常高,同异步混合链及anchor功能的结合使用可以灵活处理很多复杂初始化场景,但是要充分理解使用功能时的线程场景哦。
如果你还在梳理凌乱无序的启动任务而烦恼,又或者为任务的同异步任务控制而心烦,anchors绝对适合你哦
如果对启动场景有任何疑惑或者框架设计的意见与建议,欢迎评论留言~
分享一份大佬收录整理的Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料
这些都是我现在闲暇还会反复翻阅的精品资料。相信可以有效的帮助大家掌握知识、理解原理。
你也可以拿去查漏补缺,提升自身的竞争力。
如果你有需要的话,可以私信我【提升】获取
互联网行业是一个知识迭代非常快的行业,如果你不养成学习的习惯,其他人不会停下来等你,这样的话你就等于一直在退步!
在一个学习氛围强的圈子跟我们一起学习吧~
关于anchors是什麼意思和一个更贴近 android 场景的启动框架 | Anchors的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。