android framework之Applicataion启动流程分析(四)

news/2024/10/17 13:30:35/

本文主要学习并了解Application的Activity启动流程。


这边先分析一下Launcher是如何启动进程的Acitivity流程。从Launcher启动Acitivity的时候,它是把启动任务丢给instrumentation模块去协助完成,由它进一步调用AMS的startActivity()方法
去启动(Binder跨 进程调用),从调用启动startActivity()开始到Activity启动调用onResume(),大约经历非常多个步骤。

过一下启动Activity的大致分析(假设以ActivityA->ActivityB):

  • 1.Activity参数解析 (存在于AMS:systemserver进程)

Activity的启动流程是使用Intent的方式,作为参数传入,因此启动Activity的初始重要步骤是需要解析Activity需要的启动参数。

  • 2.Activity的管理(存在于AMS:systemserver进程)

在Framework中Activity是由谁管理的?其实是由activityStack进行管理,但在AMS服务中,它对应的代表是ActivityRecord,也就是说在ActivityStack中管理的对象的ActivityRecord,所以启动activity时,需要借助activityStack,由它去管理与启动activity.比如activityA->activityB时,B启动时,一定会影响A的生命周期,这些都需要由ActivityStack去管理。

  • 3 进程间通信

前面2小点是在AMS中处理,它属于SystemServer进程,但是对于activity的很多工作,需要由Application进程去操作 ,这就涉及到了IBinder进程间通信

  • 4.application的处理

在AMS中,将对应的Application的生命周期的所有事务都会在activityStackSupervisor类中被封装成一个clientTransaction的触发事件,它包含了操作Application activity的一系列的命令,然后借助Binder,将clientTransaction传递给Application,Application拿到命令后,去执行Application Activity的生命周期。

  • 5 Activity-A生命周期stop的执行
     

  • 下面先来学习Activity参数的解析(即上面说的第一阶段:Activity参数解析)

分析过程依据下面的流程进行,

                                                                图1

instrumentation跨进程调用ATMS的startActivity(), ATMS会调用自己的startActivityAsUser(),这是按用户的需求启动activity,这个接口里会去解析
用户的参数需求,
ATMS->startActivityAsUser()://1 理解ActivityStarter类:这是一个重要的类,专门负责activity的启动时的参数解析//2 理解ActivityStartController类:负责生产ActivityStarter对象,由controller创建//3 ActivityStartController在ATMS中的initialize()中被创建:mActivityStartController = new ActivityStartController(this);ATMS里只有一个startController对象,利用它来辅助ATMS来管理starter对象,每个activity对应一个activityStart.-->getActivityStartController().obtainstarter(intent, "startActivityAsUser")....()..().execute(); //会初始化Request内部类对象-->ActivityStartController.java->obtainStarter():-->return mFactory.obtain().setIntent().setReason();-->ActivityStarter.java->execute():-->//插入补充内容: ActivityStarter内部有一个内部类Request:由上面设置,存放activity启动过程中的交互性参数。//如A->B,需要记录A作为caller,caller是IAPPlicationThread对象,是谁启动了B,这个是要记录的。//这里面保存着启动actity启动所需要的各类参数配置,非常重要。executeRequest(mRequest); //利用Request配置好的参数去执行。-->在里面开始解读Request中的各类参数,并进行一系列的参数判断,然后会调用下面这个关键函数//Activity在AMS里的存在代表是ActivityRecord,它里面包含着activity的所有属性final ActivityRecord r = new ActivityRecord();//创建要启动的目标activityRecord对象(即ActivityB),存放到传入数组0索引上mController.doPendingActivityLaunches(false);//启动那些需要启动,但是一直没来得及启动的Activitys.-->starter.startResolvedActivity();-->startActivityUnchecked(); //启动等待的activity...startActivityUnchecked();//启动最后需要启动的activity,也就是当前Activity.--> startActivityInner(); //进一步深入分析,可以感受到starter的价值。-->setInitialState();//初始化配置,mStartActivity,mLaunchMode等computerLauncherTaskFlags();//计算要启动的activity flag标志,也就是计算启动模式。computerSourceStack();//计算源Activity所在的栈。mIntent.setFlags(mLaunchFlags);//LaunchFlags设置给Intent,也就是设置启动模式。//...这里有一个细节,如果是Launcher启动activity时,需要能让用户感知已经在启动,所以在这加了黑白屏操作//如上图所示。mTargetStack.startActivityLocked(mStartActivity,...); //开始启动//需要注意,此时我们要启动的Activity对应的Application进程并未启动,但Activity必须依附到进程上。//RootWindowContainer:窗口容器:定义了windows的存储的层次结构,设备上所有的窗口(window),显示(Disply)都是由它管理的,//每个activity均对应一个windows,每个windows的显示、隐藏与activity的生命周期有关,//所以启动activity时走到了RootWindowContainer这个类里面mRootWindowContainer.resumeFocusedStacksTopActivities();-->RootWindowContainer.java:会恢复对应任务栈顶部的Activity.即将处于栈顶的activity进行恢复,//在启动activity时,就是往这个栈的栈顶上去添加一个新的activity,这边涉及到activity的显示过程。focusedStack.resumeTopActivityUncheckedLocked(); //走到这步就意味着走到了前面文章刚开始说的第2阶段。

  • 下面开始分析第二阶段的工作任务:整体 流程如下图所示

                                                        图2.

前面说过,解读参数的过程中会创建ActivityRecord,最后会走到RootWindowContainer容器类,由它去调用resumeTopActivityUncheckedLocked,进入ActivityStack
类的中去处理,这个是第二阶段,下面来分析下ActivityStack如何去管理  ActivityRecord,管理它的启动的。
ActivityStack.java->resumeTopActivityUncheckedLocked():-->resumeTopActivityInnerLocked(): //管理栈的接口-->if(!hasRunningActivity)://不存在 正在运行的activity的时候return resumeNextFocusableActivityWhenStackIsEmpty();//当A->B时,A要先进入onPauseif(mResumedActivity != NULL){pausing |= startPausingLocked();//停止当前Activity的生命周期-->ActivityStack.java:startPausingLocked()mAtmService.getLifeCycleManager().scheduleTransaction(.., PauseActivityItem.obtain() ); //通过它来停止}//next就是要启动的这个ActivityRecord,它是一个全新的ActivityRecord,所以这里的返回值是false.ActivityRecord next = TopRunningActivity(true);if(next.attachedToProcess()) //需要与Application进程关联,但 由于它是刚创建 ,application进程创建消息还未发送,所以这边是false-->return hasProcess() && app.hasThread();-->return app != NULL; //此时app==NULLelse{ //所以会走这边,这里要注意一下//启动指定的Activity. 从这开始ActivityStackSupervisor类开始登场。它用于管理ActivityStack的类,是ActivityStack的主管。//ActivityStackSupervisor类需要封装clientTransaction事件-->传给 app进程mStackSupervisor.startSpecificActivity(next, true,true);-->//这里进入了创建app进程的起点了。可以参考前面的这篇文章《android framework之Applicataion启动流程分析》if(wpc != null && wpc.hasThread() ) { //进程如果已经创建的话,直接启动Activity.我们现在看这边realStartActivityLocked(r,wpc, andResume=true, checkConfig);--> //创建ClientTransaction对象,这个类extends Parcelable:因为它代表activity生命周期要执行的事件,//这个事件的发送目标是ActivityThread(APP进程), 由ActivityThread收到事件后进一步处理,所以//这边涉及到了跨进程通信,binder跨进程通信的数据必须继承Parcelable数据类型实现序列化。//这个类中主要包含三个内容:1. private List<ClientTransactionItem> mActivityCallbacks; //activity的回调:如onstart,onresume,onpause等2. 此变量定义了activity生命周期的最终状态(执行完一系列事件后的最终状态):private ActivityLifecycleItem mLifecyclesStateRequest.3. 跨进程的目标进程:IApplicationThread mClient; //clientTransaction的发送目标。4. 目标进程对应关联的Activity: private IBinder mActivityToken;final ClientTransaction clientTransaction  = ClientTransaction.obtain(proc.getThread(), r.apptoken);//添加LauncherActivityItem.why?clientTransaction.addCallback(LauncherActivityItem.obtain(new Intend(r.intent),... ));if(andResume)//最终的状态lifecycleItem =  ResumeActivityItem.obtain()elselifecycleItem = PauseActivityItem.obtain();clientTransaction.setLiftcycleStateRequest(liftcycleItem); //设置ResumeActivityItem到事件中。mService.getLiftcycleManager.scheduleTransaction(clientTransaction);//获取生命周期管理 类,并执行事务。}else{ //如果APP进程不存在mService.startProcessAsync(); //进入创建进程的流程。 这边的流程分支已经分析过了}}

  • 下面开始分析第三阶段的工作任务(进程间通信):整体 流程如下图所示

前面第二阶段中,将mService.getLiftcycleManager.scheduleTransaction(clientTransaction);代码执行完就,就开始进入第三阶段的处理了。

                                                                图3

接着前面的代码进行分析,当拿到LifecycleManager对象之后,继续调用它的方法scheduleTransaction(), 进入代码:

mService.getLiftcycleManager.scheduleTransaction(clientTransaction);
mService是ATMS对象mService.getLiftcycleManager():它返回的是ClientLifecycleManager,它的初始化也是在ATMS的构造函数中,
ActivityTaskManagerService(Context context)mLifecycleManager = new ClientLifecycleManager(); //28之后添加的对activity lifecycle的触发器scheduleTransaction()://这个是执行  mLifecycleManager对象中的方法-->//当前的进程还是存在于AMS所在的进程中。transaction.schedule(); //transaction是ClientTransaction对象-->会进入ClientTransaction.java->schedule(); //这个会完成一次跨进程通信-->把this(自己)传递进入:就是ClientTransaction对象-->mClient.scheduleTransaction(this); //通过mClient(目标进程的Binder)也就是IApplicationThread跨进程调用到应用进程

接着,现在源码转至APP进程的ActivityThread.java->scheduleTransaction(this):

  -->ActivityThread.this.scheduleTransaction(transaction); -->先来了解下ActivityThread extends ClientTransactionHandler,后者是ActivityThread的父类,-->这里它调用的是父类ClientTransactionHandler中的方法scheduleTransaction://下面调用发送消息所在的线程不是主线程,它是在ApplicationThread线程中运行的,就是上面分析的mClient对象,它是IBinder对象,属于binder中的ApplicationThread对象-->在里面调用了sendManager(ActivityThread.H.EXECUTE_TRANSACTION, transaction); //发消息给主线程:ActivityThread的Handler-->ActivityThread的handleMessage():-->ClientTransaction transaction = (ClientTransaction)msg.obj; //所以这个消息的传递总的来说,先跨进程,再跨线程,将封装的transaction传递过来-->mTransactionExecutor.execute(transaction); //使用主线程中的触发器去执行transaction-->//这里就进入到activity生命周期的触发管理执行

总结下第三阶段干的任务:上图3中的ClientTransaction流程中,会进行一次跨进程调用,进入到app的进程,在主进程中会调用Binder线程IAppicationThread中的方法(它是app的子线程),就是在ClientTransactionHandler中会向主线程发送消息,这里又进行了一次子线程向主线程的消息传递过程,主线程在处理的时候,就会调用真正的执行触发器   mTransactionExecutor 去执行对应的transaction,触发生命周期的管理。
             

  •   下面分析Acitivity生命周期触发器执行阶段

/第四阶段:
mTransactionExecutor.execute(transaction); //上接第三阶段结束-->executeCallbacks(transaction);-->执行的是LauncherActivityItem: //在第二阶段中有添加这个callbackint size = callbacks.size();for(int i = 0; i < size; ++i){ //从callback数组中取出itemClientTransactionItem item = callback.get(i);//调用launchActivityItem的execute方法item.execute(mTransactionHandler, token, mPendingActtions);-->进入launchActivityItem.java->execute://launcher启动activity时,还没有ActivityClientRecord,需要构建一个。//这个是ActivityThread的静态内部类:ActivityClientRecord:处理client端事件的记录,启动过程中会使用-->ActivityClientRecord r = new ActivityClientRecord();client.handleLauncherActivity(r, pendingActions); //client:ClientTransactionHandler.java//client唯一的实现类就是ActivityThread(继承ClientTransactionHandler)//所以将会进入到ActivityThread.java->handleLauncherActivity():-->final activity a = performLauncherActivity(r, customIntent);-->构建一个activityactivity = mInstrumentation.newActivity();//loadedAPk 构建makeApplication对象Application app = r.packageInfo.makeApplication(false, mInstrumentation);-->如果Application已经存在,直接return,保证单例if(mApplication != null){return mApplication; //在前面分析的bindApplication()中实际上已经创建了Application.}//在这个方法中创建Activity的PhoneWindow, 并绑定对应的WindowManager.activity.attach();-->mWindow = new PhoneWindow(); //这里开始就进入了wms....//执行onCreate生命周期mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);r.setState(ON_CREATE); //设置mLifecycleState成CREATE状态。 //这很关键}executeLifecycleState(transaction);-->获取ActivityLifecycleItem,这里取的是之前添加的ResumeActivityItemActivityLifecycleItem  lifecycleItem = transaction.getLifecycleStateRequest();...//ResumeActivityItem的getTargetState 是ON_RESUME = 3cycleToPath(r, lifecycleItem.getTargetState(), true, transaction);-->start =  r.getLifecycleState(); //这里的start是on_Create状态 = 1-->下面的path:包括ON_START和ON_RESUME-->这里是Activity执行onStart的函数的关键所在-->//mHelper是TransactionExecutorHelper类对象,finish=lifecycleItem.getTargetState(), = ON_RESUME=3-->IntArray path = mHelper.getLifecyclePath(start,finish,excludeLastState); //start = 1, finish = 3-->if(finish > start) //3> 1{if(start == ON_START && finish == ON_STOP){}else{ //走下面这个分支for(int i = start +1; i <= finish; ++i){mLifecycleSequence.add(i); //把ON_START和ON_RESUME添加到mLifecycleSequence中 。加入2和3}}}//excludeLastState = true;所以进入分支移除ON_RESUMEif(excludeLastState && mmLifecycleSequence.size()!=0){mLifecycleSequence.remove(mLifecycleSequence.size() -1);//移除ON_RESUME;}return mLifecycleSequence; //里面只有ON_START=2这个状态了//执行paht中相关的生命周期函数performLifecycleSequence(r,path,transaction);-->int size = path.size(); //只有一个ON_STARTfor(i= 0; i < size; ++i){state = path.get(i);switch(state){case ON_START:mTransactionHanlder.handleStartActivity(r.token, mPendingActions);-->触发进行Activity的onStart流程。//startactivity.performStart("handleStartActivity");r.setState(ON_START);break;}}//执行ResumeActivityItem的executelifecycleItem.execute();//lifecycleItem = ResumeActivityItem-->进入ResumeActivityItem.java->execute():client.handleResumeActivity(); //把事件丢给ActivityThread去执行。lifecycleItem.postExecute(r,path,...);//上接:  client.handleResumeActivity(); //把事件丢给ActivityThread去执行。
ActivityThread->handleResumeActivity():-->r.activity.performResume(r.startsNotResume, reason);r.setState(ON_RESUME);

总结:
LaunchActivityItem:
    launch():
      onCreate();

    触发器的计算触发onStart();生命周期

最后是ResumeAtivityItem->onResume(); 这就包括了完整的生命周期过程,从onCrate->onStart->onStart();

  • 第五阶段:activity的Stop阶段

下面分析:当Activity A--->Activity B时,B的启动和A的Stop处理如何操作?主要是A的Stop阶段如何进行?这个就是第5阶段,还是从ActivityThread的handleResumeActivity()中去分析,

大致由下图流程:

ActivityThread->handleResumeActivity():-->ActivityClientRecord r = performResumeActivity(); //执行resume生命周期...//显示UIwm.addView(decor,l);//调用windowsManagerImpl将decorView添加到window中 WMS阶段去研究吧Looper.myQueue().addIdleHandler(new Idler()) ;//往 looper中添加Idler事件//这个Idler中包括了一个相当重要的事务,包含了一个与AMS的通信。//APP主线程当没有任何消息事务需要处理时,会去处理Idler的MessageQueue
class Idler implements MessageQueue.IdleHandler{public bool queueIdle(){IActivityManager am = ActivityManager.getService();do{am.activityIdle(a.token, a.createdConfig, stopProfiling);prev = a;a = a.nextIdle;prev.nextIdle = null;}(a != NULL); //执行这里,说明主线程是空闲状态。}
}

请看上图的流程中,ASS的第4步,会处理processStoppingAndFinishingActivities();
也就是说,当ActivityThread主线程空闲时,会执行activityIdle(),接着会通过ATMS调用ASS有activityIdleInternal(),然后会执行Stop Activity相关的操作,也就是ActivityA->ActivityB过程时,会先启动B,然后在空闲时,再处理A的Stop事件,就是在这里处理的。

所以先来看看ATMS->activityIdle():
 

ATMS->activityIdle()://mStackSupervisor是对activity生命周期事件进行封装的模块。帮助activityStatemStackSupervisor.activityIdleInternal();-->processStoppingAndFinishingActivities(); //需要停止需要终止的activity都在这里面处理。-->for(int i = mStoppingActivies.size()-1; i >=0; --i){ //需要停止的遍历一遍...readyToStopActivities.add(s);mStoppingActivies.remove(i);}-->for(int i = 0; i < numReadyStops; i++){ActivityRecord r = readyToStopActivities.get(i);if(r.finishing()){r.destroyIfPossible(reason);}else{r.stopIfPossible(); //我们stop走这边-->mATmService.getLifecycleManager().scheduleTransaction(); //把stop事件封装成一个Transaction事务。-->final ClientTransaction clientTransaction = transactionWithState(); //封装scheduleTransaction(clientTransaction);//调用,跨进程,传给application.}}

注意:在android12中,activityStack和ActivityStack已经不存在了,改成了Task.java,启动过程全部转接到Task.java中处理。总体的思路不变。

在Stop事件封装成Transaction后,发给Application线程处理,然后会进入到第4阶段的Activity生命周处理处理流程,只不过可能是Launcher进程(另外一个进程),当然如果是相同进程,则由本进程去处理。只不过对于Stop或Finish等事件,它的优先级不高,所以基本都会等到主线程不繁忙空间的时候去执行清理操作。


http://www.ppmy.cn/news/1103856.html

相关文章

0基础学习VR全景平台篇 第97篇:VR步进式漫游

蛙色VR步进式漫游正式上线&#xff01; 为全行业室内场景提供三维空间重建能力&#xff0c;基于真实场景复刻&#xff0c;多维展示打破线下时空限制&#xff0c;提供高性价比的VR空间应用解决方案。 一、什么是步进式漫游&#xff1f; VR步进式漫游&#xff0c;基于AI特征点提…

【C++基础】实现日期类

​&#x1f47b;内容专栏&#xff1a; C/C编程 &#x1f428;本文概括&#xff1a; C实现日期类。 &#x1f43c;本文作者&#xff1a; 阿四啊 &#x1f438;发布时间&#xff1a;2023.9.7 对于类的成员函数的声明和定义&#xff0c;我们在类和对象上讲到过&#xff0c;需要进行…

Golang RabbitMQ实现的延时队列

文章目录 前言一、延时队列与应用场景二、RabbitMQ如何实现延时队列实现延时队列的基本要素整体的实现原理如下 三、Go语言实战生产者消费者 前言 之前做秒杀商城项目的时候使用到了延时队列来解决订单超时问题&#xff0c;本博客就总结一下Golang是如何利用RabbitMQ实现的延时…

2.12 PE结构:实现PE字节注入

本章笔者将介绍一种通过Metasploit生成ShellCode并将其注入到特定PE文件内的Shell注入技术。该技术能够劫持原始PE文件的入口地址&#xff0c;在PE程序运行之前执行ShellCode反弹&#xff0c;执行后挂入后台并继续运行原始程序&#xff0c;实现了一种隐蔽的Shell访问。而我把这…

51单片机的智能台灯控制系统仿真( proteus仿真+程序+原理图+报告+讲解视频)

51单片机的红外光敏检测智能台灯控制系统仿真 1.主要功能&#xff1a;2.仿真3. 程序代码4. 原理图5. 设计报告6. 设计资料内容清单&&下载链接 51单片机的红外光敏检测智能台灯控制系统仿真( proteus仿真程序原理图报告讲解视频&#xff09; 仿真图proteus7.8及以上 程…

AI系统论文阅读:SmartMoE

提出稀疏架构是为了打破具有密集架构的DNN模型中模型大小和计算成本之间的连贯关系的——最著名的MoE。 MoE模型将传统训练模型中的layer换成了多个expert sub-networks&#xff0c;对每个输入&#xff0c;都有一层special gating network 来将其分配到最适合它的expert中&…

celery的用法--bind=True

通过将 bindTrue 设置为 app.task 装饰器的参数&#xff0c;Celery 会自动将任务实例绑定到第一个参数&#xff08;通常命名为 self&#xff09;&#xff0c;使得你可以在任务函数内部访问任务实例的属性和方法。 在 Celery 的任务函数中&#xff0c;self 参数代表任务实例本身…

Mysql树形表的两种查询方案(递归与自连接)

你有没有遇到过这样一种情况&#xff1a; 一张表就实现了一对多的关系&#xff0c;并且表中每一行数据都存在“爷爷-父亲-儿子-…”的联系&#xff0c;这也就是所谓的树形结构 对于这样的表很显然想要通过查询来实现价值绝对是不能只靠select * from table 来实现的&#xff0…