android 9.0 startActivity流程

好记性不如烂笔杆。所以还是有必要给这些都记下来,隔段时间再看的时候也不至于一片茫然。

顺带提一下目前自己阅读源码的三种途径:1.在线阅读,类似的网站有androidxref等;2.使用工具如Source Insight 4.0导入源码进行阅读;3.使用as加载修改过的android.jar包来进行阅读。这三种更喜欢as的方式,函数的跳转和变量的颜色区分的最好,Source Insight可能用的不熟练,总感觉比as差点事,但是Source Insight好处就是占用内存资源少,而网站更适合查找部分代码,比如各个版本代码的不同部分。

好了,开始正题。startActivity在最近的几个安卓版本中部分代码做了改动,虽然整体还是一样的架构,比如;7.0之前是binder来实现进程间通信的,8.0之后改为aidl去实现了,虽然本质上实现还是binder,aidl只是又做了一层封装;又比如9.0在启动activity上与之前的启动方式相比,由函数直接调用改为类似事物的方式去启动了。但是,整体的架构还是一样的,ams仍然是那个最重要的中间者,而启动的最后仍然会回到activityThread中去处理。

在activity中调用startActivity,首先会调用Activity类中的startActivity方法,以前的老版本这一步是调用context的startActivity方法;


此方法会调用

此处传入startActivity方法的第二个参数为null,因此我们直接跟进else里面的方法startActivityForResult(intent, -1);


在此方法中我们又看到了熟悉的类Instrumentation,在Instrumentation类中调用了execStartActivity,需要注意的是这是个重载方法,我们只找我们参数对应的方法即可,下面是这个方法的关键代码


此处开始进程切换。ActivityManager.getService().startActivity这段代码其实是跨进程调用了ActivityManagerService里面的方法startActivity,关于ActivityManagerService这个服务(以下简称AMS)的作用此处不做讲解。下面来看下ActivityManager.getService()这个方法的具体实现


可以看到getService方式内部调用了IActivityManagerSingleton.get(),IActivityManagerSingleton其实是一个泛型单例类,核心实现是重写的create方法,此方法内部通过调用ServiceManager.getService(Context.ACTIVITY_SERVICE)得到一个java层的binder,ServiceManager是系统Service服务的管家,内部维护了一个map来存储各个Service对象,ACTIVITY_SERVICE就是AMS在map的key值。IActivityManager.Stub.asInterface(b)这行代码就属于aidl的范畴了,asInterface方法据说内部调用了native方法通过binder驱动,然后经过映射找到另一个进程的binder,然后层层返回,最后到java层,这样我们就拿到了可以和另一个进程进行通信的钥匙。

8.0之前这一部分没有使用aidl,而是直接使用binder实现的,具体的代码在ActivityManagerNative这个类里面。替换为binder之后代码更为精简了,便于阅读,对于初学者也更为友好,不用在ActivityManagerNative和代理类之间绕来绕去的,而机器生成的代码比人写的代码也更为安全。

接下来继续startActivity的流程,代码在系统进程AMS的startActivity处开始


此处留意第一个参数IApplicationThread caller,后续有用


第二个startActivityAsUser方法也是和之前不一样的地方,obtainStarter方法通过工厂模式生成了一个ActivityStarter对象。真正的代码跑到了ActivityStarter的execute方法里面:


这样启动activity的主要流程就跑到ActivityStarter类里面了,接下来看startActivity方法


此方法里面又调用了一个startActivity方法,而这个startActivity方法代码就比较多了,主要对activity启动的权限和调用者等做了校验,不关注这个直接走到方法底部还是一个startActivity方法,下面贴上这个startActivity方法的代码


startActivityUnchecked方法,此方法也比较长,主要对activity的启动模式和activity栈做了处理,onNewIntent就是在这触发的


接下来又跳转到了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法


ActivityStack类的resumeTopActivityUncheckedLocked方法,这个方法也比较长,只关注最后面的startSpecificActivityLocked方法


ActivityStackSupervisor类startSpecificActivityLocked方法:


startSpecificActivityLocked方法里面对是应用内打开activity还是从桌面打开activity做了判断,如果从桌面打开activity,此时应用还没有主进程,就会调用mService.startProcessLocked方法创建新的进程,然后再走startActivity的流程。此处我们关注realStartActivityLocked方法,带上real就证明离真相很近了。


此处是9.0与8.0最大的区别,改用事物的方式去启动activity了,接下来看事物的提交scheduleTransaction方法


调用的是ClientTransaction类的schedule方法,接下来看schedule方法


调用了mClient对象的方法,mClient是一个继承了IApplicationThread接口的实现类,是不是很眼熟,和前面的caller类型一样,而IApplicationThread的实现类是ApplicationThread,ActivityThread的内部类


好的,又调用了ActivityThread类的scheduleTransaction方法,搜索了一下ActivityThread类里面并没有这个方法,这个时候不要慌,看下ActivityThread的父类ClientTransactionHandler,发现原来这个方法在父类里面实现了


又给ActivityThread发送了一个消息,接下来看处理这个消息的代码


这个事务在这又被mTransactionExecutor的方法execute给执行了。。。

接下来看TransactionExecutor类的execute方法


在这个方法里面主要执行了两个方法,根据名字判断executeLifecycleState可能只是改变状态而executeCallbacks方法可能更有料,接下来看executeCallbacks方法的代码


然后继续跟item.execute这行代码,可以看到item是ClientTransactionItem类的对象,那么这个对象在哪被复制的,回到事务最初创建的地方,ActivityStackSupervisor类的realStartActivityLocked方法


可以看到此处的clientTransaction调用了addCallback方法,而刚才的executeCallbacks方法中出现了clientTransaction.getCallbacks方法,因此这个LaunchActivityItem就是item,接下来看LaunchActivityItem类中的execute方法


可以看到client.handleLaunchActivity这段代码就是之前8.0中的代码,兜兜转转这么久,终于回到了这里,而这个client就是前面继承了ClientTransactionHandler的ActivityThread类,接下来看handleLaunchActivity代码的实现


其中的关键方法performLaunchActivity,其中完成了activity实例的创建,Application的实例化,window的依附等操作,activity的生命周期也开始启动,至此activity的创建就算告一段落了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容