精华内容
参与话题
问答
  • activity启动流程简述

    千次阅读 2017-05-26 20:17:46
    Activity是Android四大组件中唯一与用户...由于Activity启动过程复杂,代码量大,这里就不贴代码了,直接写调用的函数和作用. 发起进程: Activity.startActivity() Instrumentation.execStartActivity() 调用标准语句A

    Activity是Android四大组件中唯一与用户交互的组件,也是最重要,最复杂的组件, 这里以在新进程中启动Activity为例介绍其启动流程.由于Activity启动过程复杂,代码量大,这里就不贴代码了,直接写调用的函数和作用.


    发起进程:

    Activity.startActivity()
    Instrumentation.execStartActivity()
    调用标准语句ActivityManagerNative.getDefault().startActivity(args...)进入AMS

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    system_server进程:

    ActivityManagerService.startActivity()
    ActivityStackSupervisor.startActivityMayWait()
    解析intent,并把信息保存在ActivityInfo中。如果有多个activity满足要求,弹出对话框让用户选择。
    ActivityStackSupervisor.startActivityLocked()
    根据resultTo参数在activity stack里面查找调用者的ActivityRecord,以及创建被启动activity的ActivityRecord。
    ActivityStackSupervisor.startActivityUncheckedLocked()
    根据启动模式找到或创建activity所属于的任务栈,进行任务栈的相关操作.这里注意一点,如果intent里面的启动模式与AndroidManifest.xml文件里面的启动模式冲突,以AndroidManifest.xml文件为准.
    ActivityStack.startActivityLocked()
    将目标activity添加到task stack的顶端并将其设置为前台任务.
    ActivityStackSupervisor.resumeTopActivitiesLocked()
    ActivityStack.resumeTopActivityInnerLocked()
    暂停当前显示的activity
    ActivityStackSupervisor.startSpecificActivityLocked()
    判断是否需要新建进程,如果不需要,则直接调用realStartActivityLocked启动activity,需要就调用startProcessLocked创建进程。我们这里需要创建进程。
    ActivityManagerService.startProcessLocked()

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    目标应用进程:

    创建新进程,并执行新进程的ActivityThread.main()方法
    ActivityThread.attach()
    从main进入attach()后,再通过Binder进入AMS的attach()方法,并将新进程的ApplicationThread对象传给AMS,ApplicationThread是一个binder,用于后期AMS给目标进程注册binder死亡通知和与其IPC通信.

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    system_server进程:

    ActivityManagerService.attachApplicationLocked()
    先给目标进程的ApplicationThread注册binder死亡通知,然后初始化目标进程的ProcessRecord,再通过从目标应用进程传递过来的ApplicationThread对象进入目标进程并初始化目标进程的运行环境。
    ActivityStackSupervisor.attachApplicationLocked()
    最后在ActivityStackSupervisor.realStartActivityLocked()方法里面进入目标应用进程.

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    目标应用进程:

    ActivityThread.handleLaunchActivity()
    首先调用performLaunchActivity()加载activity实例,并创建application,contextImpl和config等运行环境并通过activity.attach()方法将这些对象保存在activity实例内部,以便activity可以访问。
    在activity.attach()里面首先创建了与activity对象关联的PhoneWindow对象,然后创建WindowManagerImpl对象,用于本地端窗口管理。
    attach()方法执行结束后回调Activity的onCreate()和onStart()方法。在应用重写onCreate()方法的时候,通过调用PhoneWindow.setContentView()方法创建activity的根视图DecorView并加载布局文件,将layout.xml文件解析出来后作为子view添加到DecorView中.
    至此,activity的对象实例,对应的PhoneWindow对象和DecorView对象都已经创建完成。
    接下来调用handleResumeActivity()方法将activity显示出来.
    该方法首先调用performResumeActivity告诉activity进入resume状态并回调onResumed()方法。
    然后调用WindowManager.addView()方法创建ViewRootImpl并与WindowManager.LayoutParams和DecorView关联。
    最后调用ViewRootImpl.setView()方法,该方法首先调用requestLayout()方法请求UI做第一次布局,在requestLayout()方法调用ViewRootImpl.performTraversals()方法,在该方法里面依次调用performMeasure(),performLayout(),performDraw()对视图进程测量布局和绘制;然后调用IWindowSession.addToDisplay()方法向WMS请求给当前窗口创建一个WindowState;最后创建与InputManager的链接以便接收键盘和屏幕事件。
    到此activity就启动完成,并显示到界面上。

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    总结:
    在新进程中启动activity总体可分为5个阶段:
    1. 启动进程调用startActivity()
    2. AMS做一系列的准备工作:
       1) 解析intent并保存在activityInfo中
       2) 如果有多个activity满足要求,则弹出对话框让用户选择
       3) 根据启动模式进行任务栈的操作,找出或创建activity应该属于的任务栈,并将activity放到栈顶
       4) 暂停当前显示的activity
       5) 创建新进程
    3. 执行新建进程的ActivityThread.main()方法, 然后attach到AMS,并将新进程的ApplicationThread对象传给AMS.该对象是个binder代理对象.
    4. AMS再做几件事:
       1) 给目标进程的ApplicationThread对象注册binder死亡通知
       2) 创建目标进程的ProcessRecord.
       3) 初始化目标进程的运行环境
    5. 进入目标进程创建并显示activity
       1) 加载activity实例,并创建application,contextImpl和config等对象.
       2) 创建与activity关联的PhoneWindow和WindowManagerImpl对象
       3) 回调activity的onCreate()和onStart()方法
       4) 在onCreate()方法中调用setContentView()方法创建activity的根视图DecorView并加载layout文件到DecorView.
       5) 回调activity的onResume()方法,然后创建ViewRootImpl并调用setView方法进行界面的绘制
       6) 创建与InputManager的连接以便接收键盘和触摸屏事件.

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


    Binder死亡通知机制:
    进程在运行过程中可能异常退出,就会导致运行在进程里面的binder代理对象和binder本地对象异常死亡,比较严重的是binder本地对象的死亡会导致binder代理对象的无效.binder死亡通知机制就是为了解决这个问题而设计的.
    死亡通知机制会监控到binder本地对象的死亡事件,然后通知引用了这些binder本地对象的binder代理对象.在这机制中binder代理对象会向binder驱动注册一个死亡接收通知,binder驱动监控binder本地对象死亡后就会通知对应的binder代理对象.binder代理对象在不需要接收死亡通知的时候,可以注销.


    展开全文
  • Android的Activity启动流程分析

    万次阅读 多人点赞 2019-06-10 22:38:41
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------...

     

     

     

     

     

     

     

     


    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 

    • app进程通过ActivityManager.getService (高版本)或者 ActivityManagerNative.getDefault(低版本)返回的IActivityManager来调用系统进程AMS中的方法。该IActivityManager是AMS在app进程的binder代理对象
    • 同样,系统进程通过ProcessRecord.IApplicationThread调用app进程相关方法。IApplicationThread是系统进程持有的app进程中ApplicationThread的Binder代理对象。
    • AMS通过binder代理调用到ApplicationThread(ActivityThread的内部类)中的方法后,通过主线程(ActivityThread中的main方法)中开启的handler消息轮询来通知主线程调用相关方法。主线程的相关声明周期方法的具体实现会委托给Instrumentation类实现,在Instrumentation类中,会调用具体组件的相关生命周期方法。

    Activity启动之前的一些事情

    • init进程:init是所有linux程序的起点,是Zygote的父进程。解析init.rc孵化出Zygote进程。

    • Zygote进程:Zygote是所有Java进程的父进程,所有的App进程都是由Zygote进程fork生成的。

    • SystemServer进程:System Server是Zygote孵化的第一个进程。SystemServer负责启动和管理整个Java framework,包含AMS,PMS等服务。

    • Launcher:Zygote进程孵化的第一个App进程是Launcher。

      1.init进程是什么?

      Android是基于linux系统的,手机开机之后,linux内核进行加载。加载完成之后会启动init进程。
      init进程会启动ServiceManager,孵化一些守护进程,并解析init.rc孵化Zygote进程。

      2.Zygote进程是什么?

      所有的App进程都是由Zygote进程fork生成的,包括SystemServer进程。Zygote初始化后,会注册一个等待接受消息的socket,OS层会采用socket进行IPC通信。

      3.为什么是Zygote来孵化进程,而不是新建进程呢?

      每个应用程序都是运行在各自的Dalvik虚拟机中,应用程序每次运行都要重新初始化和启动虚拟机,这个过程会耗费很长时间。Zygote会把已经运行的虚拟机的代码和内存信息共享,起到一个预加载资源和类的作用,从而缩短启动时间。

    Activity启动阶段

    涉及到的概念

    • 进程:Android系统为每个APP分配至少一个进程
    • IPC:跨进程通信,Android中采用Binder机制。

    涉及到的类

    • ActivityStack:Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
    • ActivitySupervisor:管理 activity 任务栈
    • ActivityThread:ActivityThread 运行在UI线程(主线程),App的真正入口。
    • ApplicationThread:用来实现AMS和ActivityThread之间的交互。
    • ApplicationThreadProxy:ApplicationThread 在服务端的代理。AMS就是通过该代理与ActivityThread进行通信的。
    • IActivityManager:继承与IInterface接口,抽象出跨进程通信需要实现的功能
    • AMN:运行在server端(SystemServer进程)。实现了Binder类,具体功能由子类AMS实现。
    • AMS:AMN的子类,负责管理四大组件和进程,包括生命周期和状态切换。AMS因为要和ui交互,所以极其复杂,涉及window。
    • AMP:AMS的client端代理(app进程)。了解Binder知识可以比较容易理解server端的stub和client端的proxy。AMP和AMS通过Binder通信。
    • Instrumentation:仪表盘,负责调用Activity和Application生命周期。测试用到这个类比较多。
    • ActivityStackSupervisor
      负责所有Activity栈的管理。内部管理了mHomeStack、mFocusedStack和mLastFocusedStack三个Activity栈。其中,mHomeStack管理的是Launcher相关的Activity栈;mFocusedStack管理的是当前显示在前台Activity的Activity栈;mLastFocusedStack管理的是上一次显示在前台Activity的Activity栈。
       



     

    ActivityThread.java    路径位于:\frameworks\base\core\java\android\app\ActivityThread.java

             说明: 该类为应用程序(即APK包)所对应进程(一个进程里可能有多个应用程序)的主线程类,即我们通常所说的UI线程。

               一个ActivityThread类对应于一个进程。最重要的是,每个应用程序的入口是该类中的static main()函数 。

     Instrumentation.java  路径位于 :\frameworks\base\core\java\android\app\ActivityThread.java

             说明: 该类用于具体操作某个Activity的功能----单向(oneway)调用AMS以及统计、测量该应用程序的所有开销。

                一个Instrumentation类对应于一个进程。每个Activity内部都有一个该Instrumentation对象的引用。

     

          举个例子吧。

               我们将我们应用程序比作一个四合院,那么Activity对应于四合院的人,ActivithThread对应于院子的主人----管理所有人,

        Instrumentation对应于管家------受气的命,接受来自人(Activity/ActivithThread)的命令 ,去单向(oneway)调用AMS 。
     

    ApplicationThread类是ActivityThread的内部类:

           说明:该类是一个Binder类,即可实现跨进程通信。主要用于接受从AMS传递过来的消息,继而做相应处理。

    具体流程

    • Launcher:Launcher通知AMS要启动activity。
      • startActivitySafely->startActivity->Instrumentation.execStartActivity()(AMP.startActivity)->AMS.startActivity
    • AMS:PMS的resoveIntent验证要启动activity是否匹配。
      • 如果匹配,通过ApplicationThread发消息给Launcher所在的主线程,暂停当前Activity(Launcher);
    • 暂停完,在该activity还不可见时,通知AMS,根据要启动的Activity配置ActivityStack。然后判断要启动的Activity进程是否存在?
      • 存在:发送消息LAUNCH_ACTIVITY给需要启动的Activity主线程,执行handleLaunchActivity
      • 不存在:通过socket向zygote请求创建进程。进程启动后,ActivityThread.attach
    • 判断Application是否存在,若不存在,通过LoadApk.makeApplication创建一个。在主线程中通过thread.attach方法来关联ApplicationThread。
    • 在通过ActivityStackSupervisor来获取当前需要显示的ActivityStack。
    • 继续通过ApplicationThread来发送消息给主线程的Handler来启动Activity(handleLaunchActivity)。
    • handleLauchActivity:调用了performLauchActivity,里边Instrumentation生成了新的activity对象,继续调用activity生命周期。

    IPC过程:

    双方都是通过对方的代理对象来进行通信。
    1.app和AMS通信:app通过本进程的AMP和AMS进行Binder通信
    2.AMS和新app通信:通过ApplicationThreadProxy来通信,并不直接和ActivityThread通信

    参考函数流程

    Activity启动流程(从Launcher开始):

    第一阶段: Launcher通知AMS要启动新的Activity(在Launcher所在的进程执行)

    • Launcher.startActivitySafely //首先Launcher发起启动Activity的请求
    • Activity.startActivity
    • Activity.startActivityForResult
    • Instrumentation.execStartActivity //交由Instrumentation代为发起请求
    • ActivityManager.getService().startActivity //通过IActivityManagerSingleton.get()得到一个AMP代理对象
    • ActivityManagerProxy.startActivity //通过AMP代理通知AMS启动activity

    第二阶段:AMS先校验一下Activity的正确性,如果正确的话,会暂存一下Activity的信息。然后,AMS会通知Launcher程序pause Activity(在AMS所在进程执行)

    • ActivityManagerService.startActivity
    • ActivityManagerService.startActivityAsUser
    • ActivityStackSupervisor.startActivityMayWait
    • ActivityStackSupervisor.startActivityLocked :检查有没有在AndroidManifest中注册
    • ActivityStackSupervisor.startActivityUncheckedLocked
    • ActivityStack.startActivityLocked :判断是否需要创建一个新的任务来启动Activity。
    • ActivityStack.resumeTopActivityLocked :获取栈顶的activity,并通知Launcher应该pause掉这个Activity以便启动新的activity。
    • ActivityStack.startPausingLocked
    • ApplicationThreadProxy.schedulePauseActivity

    第三阶段: pause Launcher的Activity,并通知AMS已经paused(在Launcher所在进程执行)

    • ApplicationThread.schedulePauseActivity
    • ActivityThread.queueOrSendMessage
    • H.handleMessage
    • ActivityThread.handlePauseActivity
    • ActivityManagerProxy.activityPaused

    第四阶段:检查activity所在进程是否存在,如果存在,就直接通知这个进程,在该进程中启动Activity;不存在的话,会调用Process.start创建一个新进程(执行在AMS进程)

    • ActivityManagerService.activityPaused
    • ActivityStack.activityPaused
    • ActivityStack.completePauseLocked
    • ActivityStack.resumeTopActivityLocked
    • ActivityStack.startSpecificActivityLocked
    • ActivityManagerService.startProcessLocked
    • Process.start //在这里创建了新进程,新的进程会导入ActivityThread类,并执行它的main函数

    第五阶段: 创建ActivityThread实例,执行一些初始化操作,并绑定Application。如果Application不存在,会调用LoadedApk.makeApplication创建一个新的Application对象。之后进入Loop循环。(执行在新创建的app进程)

    • ActivityThread.main
    • ActivityThread.attach(false) //声明不是系统进程
    • ActivityManagerProxy.attachApplication

    第六阶段:处理新的应用进程发出的创建进程完成的通信请求,并通知新应用程序进程启动目标Activity组件(执行在AMS进程)

    • ActivityManagerService.attachApplication //AMS绑定本地ApplicationThread对象,后续通过ApplicationThreadProxy来通信。
    • ActivityManagerService.attachApplicationLocked
    • ActivityStack.realStartActivityLocked //真正要启动Activity了!
    • ApplicationThreadProxy.scheduleLaunchActivity //AMS通过ATP通知app进程启动Activity

    第七阶段: 加载MainActivity类,调用onCreate声明周期方法(执行在新启动的app进程)

    • ApplicationThread.scheduleLaunchActivity //ApplicationThread发消息给AT
    • ActivityThread.queueOrSendMessage
    • H.handleMessage //AT的Handler来处理接收到的LAUNCH_ACTIVITY的消息
    • ActivityThread.handleLaunchActivity
    • ActivityThread.performLaunchActivity
    • Instrumentation.newActivity //调用Instrumentation类来新建一个Activity对象
    • Instrumentation.callActivityOnCreate
    • MainActivity.onCreate
    • ActivityThread.handleResumeActivity
    • AMP.activityResumed
    • AMS.activityResumed(AMS进程)


    • ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------​​​​​​​


       

      一:开始请求执行启动Activity


      MyActivity.startActivity() 
      Activity.startActivity() 
      Activity.startActivityForResult 
      Instrumentation.execStartActivty 
      ActivityManagerNative.getDefault().startActivityAsUser() 

      二:ActivityManagerService接收启动Activity的请求


      ActivityManagerService.startActivity() 
      ActvityiManagerService.startActivityAsUser() 
      ActivityStackSupervisor.startActivityMayWait() 
      ActivityStackSupervisor.startActivityLocked() 
      ActivityStackSupervisor.startActivityUncheckedLocked() 
      ActivityStackSupervisor.startActivityLocked() 
      ActivityStackSupervisor.resumeTopActivitiesLocked() 
      ActivityStackSupervisor.resumeTopActivityInnerLocked() 
       

    • 三:执行栈顶Activity的onPause方法


      ActivityStack.startPausingLocked() 
      IApplicationThread.schudulePauseActivity() 
      ActivityThread.sendMessage() 
      ActivityThread.H.sendMessage(); 
      ActivityThread.H.handleMessage() 
      ActivityThread.handlePauseActivity() 
      ActivityThread.performPauseActivity() 
      Activity.performPause() 
      Activity.onPause() 
      ActivityManagerNative.getDefault().activityPaused(token) 
      ActivityManagerService.activityPaused() 
      ActivityStack.activityPausedLocked() 
      ActivityStack.completePauseLocked() 
      ActivityStack.resumeTopActivitiesLocked() 
      ActivityStack.resumeTopActivityLocked() 
      ActivityStack.resumeTopActivityInnerLocked() 
      ActivityStack.startSpecificActivityLocked 

      四:启动Activity所属的应用进程

      关于如何启动应用进程,前面的一篇文章已经做了介绍,可参考: android源码解析之(十一)–>应用进程启动流程 这里在简单的介绍一下


      ActivityManagerService.startProcessLocked() 
      Process.start() 
      ActivityThread.main() 
      ActivityThread.attach() 
      ActivityManagerNative.getDefault().attachApplication() 
      ActivityManagerService.attachApplication() 

      五:执行启动Acitivity


      ActivityStackSupervisor.attachApplicationLocked() 
      ActivityStackSupervisor.realStartActivityLocked() 
      IApplicationThread.scheduleLauncherActivity() 
      ActivityThread.sendMessage() 
      ActivityThread.H.sendMessage() 
      ActivityThread.H.handleMessage() 
      ActivityThread.handleLauncherActivity() 
      ActivityThread.performLauncherActivity() 
      Instrumentation.callActivityOnCreate() 
      Activity.onCreate() 
      ActivityThread.handleResumeActivity() 
      ActivityThread.performResumeActivity() 
      Activity.performResume() 
      Instrumentation.callActivityOnResume() 
      Activity.onResume() 
      ActivityManagerNative.getDefault().activityResumed(token) 

      六:栈顶Activity执行onStop方法


      Looper.myQueue().addIdleHandler(new Idler()) 
      Idler.queueIdle() 
      ActivityManagerNative.getDefault().activityIdle() 
      ActivityManagerService.activityIdle() 
      ActivityStackSupervisor.activityIdleInternalLocked() 
      ActivityStack.stopActivityLocked() 
      IApplicationThread.scheduleStopActivity() 
      ActivityThread.scheduleStopActivity() 
      ActivityThread.sendMessage() 
      ActivityThread.H.sendMessage() 
      ActivityThread.H.handleMessage() 
      ActivityThread.handleStopActivity() 
      ActivityThread.performStopActivityInner() 
      ActivityThread.callCallActivityOnSaveInstanceState() 
      Instrumentation.callActivityOnSaveInstanceState() 
      Activity.performSaveInstanceState() 
      Activity.onSaveInstanceState() 
      Activity.performStop() 
      Instrumentation.callActivityOnStop() 
      Activity.onStop() 

       

      总结:

    • Activity的启动流程一般是通过调用startActivity或者是startActivityForResult来开始的

    • startActivity内部也是通过调用startActivityForResult来启动Activity,只不过传递的requestCode小于0

    • Activity的启动流程涉及到多个进程之间的通讯这里主要是ActivityThread与ActivityManagerService之间的通讯

    • ActivityThread向ActivityManagerService传递进程间消息通过ActivityManagerNative,ActivityManagerService向ActivityThread进程间传递消息通过IApplicationThread。

    • ActivityManagerService接收到应用进程创建Activity的请求之后会执行初始化操作,解析启动模式,保存请求信息等一系列操作。

    • ActivityManagerService保存完请求信息之后会将当前系统栈顶的Activity执行onPause操作,并且IApplication进程间通讯告诉应用程序继承执行当前栈顶的Activity的onPause方法;

    • ActivityThread接收到SystemServer的消息之后会统一交个自身定义的Handler对象处理分发;

    • ActivityThread执行完栈顶的Activity的onPause方法之后会通过ActivityManagerNative执行进程间通讯告诉ActivityManagerService,栈顶Actiity已经执行完成onPause方法,继续执行后续操作;

    • ActivityManagerService会继续执行启动Activity的逻辑,这时候会判断需要启动的Activity所属的应用进程是否已经启动,若没有启动则首先会启动这个Activity的应用程序进程;

    • ActivityManagerService会通过socket与Zygote继承通讯,并告知Zygote进程fork出一个新的应用程序进程,然后执行ActivityThread的mani方法;

    • 在ActivityThead.main方法中执行初始化操作,初始化主线程异步消息,然后通知ActivityManagerService执行进程初始化操作;

    • ActivityManagerService会在执行初始化操作的同时检测当前进程是否有需要创建的Activity对象,若有的话,则执行创建操作;

    • ActivityManagerService将执行创建Activity的通知告知ActivityThread,然后通过反射机制创建出Activity对象,并执行Activity的onCreate方法,onStart方法,onResume方法;

    • ActivityThread执行完成onResume方法之后告知ActivityManagerService onResume执行完成,开始执行栈顶Activity的onStop方法;

    • ActivityManagerService开始执行栈顶的onStop方法并告知ActivityThread;

    • ActivityThread执行真正的onStop方法;


      ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
       

    • 启动流程进程间简单分析:

      Zygote进程 –> SystemServer进程 –> 各种系统服务 –> 应用进程 
      在Actvity启动过程中,其实是应用进程与SystemServer进程相互配合启动Activity的过程,其中应用进程主要用于执行具体的Activity的启动过程,回调生命周期方法等操作,而SystemServer进程则主要是调用其中的各种服务,将Activity保存在栈中,协调各种系统资源等操作。
      通过ActivityManagerNative –> ActivityManagerService实现了应用进程与SystemServer进程的通讯 
      通过AppicationThread <– IApplicationThread实现了SystemServer进程与应用进程的通讯
    1. ActivityManagerProxy相当于Proxy
    2. ActivityManagerNative就相当于Stub
    3. ActivityManagerService是ActivityManagerNative的具体实现,换句话说,就是AMS才是服务端的具体实现!
    4. ApplicationThreadProxy相当于Proxy
    5. ApplicationThreadNative相当于Stub
    6. ApplicationThread相当于服务器端,代码真正的实现者!
    • 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
    • system_server进程接收到请求后,向zygote进程发送创建进程的请求;
    • Zygote进程fork出新的子进程,即App进程;
    • App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
    • system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
    • App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
    • 主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。
    • 到此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。
      ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------​​​​​​​ 

    Launch Mode

    先来说说在ActivityInfo.java中定义了4类Launch Mode:

    • LAUNCH_MULTIPLE(standard):最常见的情形,每次启动Activity都是创建新的Activity;
    • LAUNCH_SINGLE_TOP: 当Task顶部存在同一个Activity则不再重新创建;其余情况同上;
    • LAUNCH_SINGLE_TASK:当Task栈存在同一个Activity(不在task顶部),则不重新创建,而移除该Activity上面其他的Activity;其余情况同上;
    • LAUNCH_SINGLE_INSTANCE:每个Task只有一个Activity.

    再来说说几个常见的flag含义:

    • FLAG_ACTIVITY_NEW_TASK:将Activity放入一个新启动的Task;
    • FLAG_ACTIVITY_CLEAR_TASK:启动Activity时,将目标Activity关联的Task清除,再启动新Task,将该Activity放入该Task。该flags跟FLAG_ACTIVITY_NEW_TASK配合使用。
    • FLAG_ACTIVITY_CLEAR_TOP:启动非栈顶Activity时,先清除该Activity之上的Activity。例如Task已有A、B、C3个Activity,启动A,则清除B,C。类似于SingleTop。

    最后再说说:设置FLAG_ACTIVITY_NEW_TASK的几个情况:

     

    • 调用者并不是Activity context;
    • 调用者activity带有single instance;
    • 目标activity带有single instance或者single task;
    • 调用者处于finishing状态;

      ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------​​​​​​​

    1、新的Activity类是通过类加载器方式即通过反射的方式生成的,我们可以看一下mInstrumentation.newActivity()方法:

    public Activity newActivity(ClassLoader cl, String className, Intent intent)
                throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }
    

    最后调用mInstrumentation.callActivityOnCreate()
     

    2、在mInstrumentation.callActivityOnStart(this)方法里面就会显式调用Activtiy的onStart()方法!

    到这里我们也可以基本解决第二个问题:Activity的生命周期方法是通过Instrumentation类调用callActivityOnXXX方法最终调用Activity的onCreate等方法,调用时机为ActivityThread#performLaunchActivitiy()方法中。

    3、ActivityThread#performResumeActivity()
      --> Activity#performResume()
        --> Instrumentation#callActivityOnResume()
          --> Activity#onResume()
    另外,观察执行handleResumeActivity()之后的代码,会发现程序会开始获取DecorView,执行addView()方法,里面最终会调用到ViewRootImpl#performTraversals(),即开始绘制view界面!
    这里我们就解决了第三个问题:界面的绘制是在执行Activity#onResume()之后!

    4、ActivityThread的main方法是在生成一个新的app进程过程中调用的,具体是通过与Zygote通信,之后通过RuntimeInit类采用反射的方式调用ActivityThread#main()方法,即生成app中的主线程(UI线程)!

     

    内容引自如下:

    https://blog.csdn.net/qinjuning/article/details/7262769

    https://www.jianshu.com/p/dc6b0ead30aa

    https://www.jianshu.com/p/274ccb315a7a

    https://www.cnblogs.com/zl1991/p/6883517.html

    https://www.cnblogs.com/ldq2016/p/6891009.html

    https://blog.csdn.net/lj19851227/article/details/82562115​​​​​​​

    https://www.jianshu.com/p/86ad1026cef3

     

    展开全文
  • 细谈Activity四种启动模式

    万次阅读 多人点赞 2018-06-06 17:04:32
    ),今天我们谈一谈我们在Android开发中必不可缺少的一个组件——Activity: Activity作为四大组件之一,也可以说是四大组件中最重要的一个组件,它负责App的视图,还负责用户交互,而且有时候还经常其他组件绑定...

        嗨大家好,又和大家见面了,上一次我们一起搞清楚了Handler的源码机制(现在回想起来是不是感觉也就那么回事,当时看的头皮发麻-。+!!),今天我们谈一谈我们在Android开发中必不可缺少的一个组件——Activity:

        Activity作为四大组件之一,也可以说是四大组件中最重要的一个组件,它负责App的视图,还负责用户交互,而且有时候还经常其他组件绑定使用,可以说非常的重要。

        虽然说我们天天都在使用Activity,但是你真的对Activity的生命机制烂熟于心,完全了解了吗?的确,Activity的生命周期方法只有七个(自己数-。+),但是其实那只是最平常的情况,或者说是默认的情况。也就是说在其他情况下,Activity的生命周期可能不会是按照我们以前所知道的流程,这就要说到我们今天的重点了——Activity的启动模式:我们的Activity会根据自身不同的启动模式,自身的生命周期方法会进行不同的调用。

    一、在将启动模式之前必须了解的一些知识:

        在正式的介绍Activity的启动模式之前,我们首先要了解一些旁边的知识,这些知识如果说模糊不清,那么在讨论启动模式的时候会一头雾水(笔者亲身感悟)。

    1.一个应用程序通常会有多个Activity,这些Activity都有一个对应的action(如MainActivity的action),我们可以通过action来启动对应Activity(隐式启动)。

    <action android:name="android.intent.action.MAIN" />

    2.一个应用程序可以说由一系列组件组成,这些组件以进程为载体,相互协作实现App功能。

    3.任务栈(Task Stack)或者叫退回栈(Back Stack)介绍:

    3.1.任务栈用来存放用户开启的Activity。

    3.2.在应用程序创建之初,系统会默认分配给其一个任务栈(默认一个),并存储根Activity。

    3.3.同一个Task Stack,只要不在栈顶,就是onStop状态:


    3.4.任务栈的id自增长型,是Integer类型。

    3.5.新创建Activity会被压入栈顶。点击back会将栈顶Activity弹出,并产生新的栈顶元素作为显示界面(onResume状态)。

    3.6.当Task最后一个Activity被销毁时,对应的应用程序被关闭,清除Task栈,但是还会保留应用程序进程(狂点Back退出到Home界面后点击Menu会发现还有这个App的框框。个人理解应该是这个意思),再次点击进入应用会创建新的Task栈。

    4.Activity的affinity:

    4.1.affinity是Activity内的一个属性(在ManiFest中对应属性为taskAffinity)。默认情况下,拥有相同affinity的Activity属于同一个Task中。

    4.2.Task也有affinity属性,它的affinity属性由根Activity(创建Task时第一个被压入栈的Activity)决定。

    4.3.在默认情况下(我们什么都不设置),所有的Activity的affinity都从Application继承。也就是说Application同样有taskAffinity属性。

    <application
            android:taskAffinity="gf.zy"

    4.4.Application默认的affinity属性为Manifest的包名。


    暂时就是这么多了,如果还有不妥的地方我会补充的。接下来我们来正式看Activity的启动模式:

    二、Activity启动模式:

    1.默认启动模式standard:

        该模式可以被设定,不在manifest设定时候,Activity的默认模式就是standard。在该模式下,启动的Activity会依照启动顺序被依次压入Task中:


    上面这张图讲的已经很清楚了,我想应该不用做什么实验来论证了吧,这个是最简单的一个,我们过。

    2.栈顶复用模式singleTop:

        在该模式下,如果栈顶Activity为我们要新建的Activity(目标Activity),那么就不会重复创建新的Activity。



    这次我来用代码举例:

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="zy.pers.activitytext">
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:taskAffinity="gf.zy"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name=".TwoActivity"
                android:launchMode="singleTop">
                <intent-filter>
                    <action android:name="ONETEXT_TWOACTIVITY" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </activity>
            <activity android:name=".ThreeActivity">
                <intent-filter>
                    <action android:name="ONETEXT_THREEACTIVITY" />
                    <category android:name="android.intent.category.DEFAULT" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    这是我的第一个应用OneText的Mainfest结构,里面创建了三个Activity,我们把第二个Activity的模式设置为singleTop。

    每个Activity界面都只有一个显示当前界面名称的TextView和一个用来组跳转的Button,所以应用OneText的功能就是从活动1跳转到活动2,活动2继续跳转活动2,代码就不给大家展示了,都能写出来。


    我们发现在我们跳转到TwoActivity之后,点击跳转新的TwoActivity时候,他没有响应。

    为了作对比,我们再把TwoActivity设置为standard,看一看效果:


    我们发现创建了很多的TwoActivity。

    同时我们打印上task的Id(我没有把所有周期方法都打印log):


    发现他们全部都是来自一个Task。这个可以过。

    应用场景:

    开启渠道多,适合多应用开启调用的Activity:通过这种设置可以避免已经创建过的Activity被重复创建(多数通过动态设置使用,关于动态设置下面会详细介绍)

    3.栈内复用模式singleTask:

        与singleTop模式相似,只不过singleTop模式是只是针对栈顶的元素,而singleTask模式下,如果task栈内存在目标Activity实例,则:

    1. 将task内的对应Activity实例之上的所有Activity弹出栈。
    2. 将对应Activity置于栈顶,获得焦点。

    同样我们也用代码来实现一下这个过程:

    还是刚才的那一坨代码,只是我们修改一下Activity1的模式为singleTask,然后让Activity2跳转到Activity3,让Activity3跳转到Activity1:


    在跳回MainActivity之后点击back键发现直接退出引用了,这说明此时的MainActivity为task内的最后一个Activity。所以这个模式过。

    应用场景:

    程序主界面,我们肯定不希望主界面被多创建,而且在主界面退出的时候退出整个App是最好的设想。

    耗费系统资源的Activity:对于那些及其耗费系统资源的Activity,我们可以考虑将其设为singleTask模式,减少资源耗费(在创建阶段耗费资源的情况,个人理解-。+)。

    4.全局唯一模式singleInstance:

        这是我们最后的一种启动模式,也是我们最恶心的一种模式:在该模式下,我们会为目标Activity分配一个新的affinity,并创建一个新的Task栈,将目标Activity放入新的Task,并让目标Activity获得焦点。新的Task有且只有这一个Activity实例。       如果已经创建过目标Activity实例,则不会创建新的Task,而是将以前创建过的Activity唤醒(对应Task设为Foreground状态)


    我们为了看的更明确,这次不按照上图的步骤设计程序了(没错,这几张图都不是我画的-。+!)。

    我们先指定一下这次的程序:还是这三个Activity,这次Activity3设置为singleInstance,1和2默认(standard)。

    然后我们看一下这个效果:


    说一下我们做了什么操作:

    首先由1创建2,2创建3,然后又由3创建2,2创建3,3创建2,然后一直back,图如下:


    还请各位别嫌弃我-。+,图虽然不好看,但是很生动形象。。。。具体说一下:这张图对应着我们上面的程序流程,黄色的代表Background的Task,蓝色的代表Foreground的Task。

    我们发现back的时候会先把Foreground的Task中的Activity弹出,直到Task销毁,然后才将Background的Task唤到前台,所以最后将Activity3销毁之后,会直接退出应用。

    但是有没有想过这样会出现一个问题,什么问题我们直接看图就好:


    我简单说一下这个案例:1,2,3三个Activity,2是singleInstance模式,然后1->2,2->3,之后狂点back,在回到Home界面后点击菜单键,发现首先启动的是2Activity。

    简单解释一下:1和3是一个task,2是单独的一个task,在我们2->3后,前台的task又从2的回到了1和3的。所以最后退出的task是2的线程,而如果不是重新启动App。上一次最后关闭的Task是2的,所以。。

    所以说singleInstance设置的Activity最好不要设置成中间界面。


    以上表示我们关于四种模式的最基本理解,其实有了前面的知识了解之后,我们发现这些其实也不是很难对吧。。。真正比较绕的在后面-。+,注意前方高能:

    三、动态设置启动模式

        在上述所有情况,都是我们在Manifest中设置的(通过launchMode属性设置),这个被称为静态设置(我们写程序写多了会发现有静态就有动态,而且静态多数在xml设置,动态在java代码设置-。+),接下来我们来看一下如何动态的设置Activity启动方式。

    注):如果同时有动态和静态设置,那么动态的优先级更高。

    1.关于动态设置与静态设置的理解:

        关于这个理解我是看过一篇文章,比较认同里面的思想,所以在这里也总结一下:

        静态设置,可以理解为通知别人:就是当我被创建的时候,我告诉你我是通过这种模式启动的。

        动态设置,可以理解为别人的要求:别人给我设一个Flag,我就以这种Flag的方式启动。

        可能这个没什么用哈,但是仔细想一下这种对程序的思想理解应该是正确的。

    2.几种常见的Flag:

        我们说的动态设置,其实是通过Intent。对与Intent这个类大家应该不陌生吧,我们刚才在启动Activity的时候就用到这个类了。

    如果我们要设置要启动的Activity的启动模式的话,只需要这样:

    intent.setFlags(、、、、、);

    然后在里面添加对应的Flag就好,那么接下来我们介绍几个常见的Flag(他的Flag太多了,头皮发麻。):

    2.1._NEW_TASK

    他对应的Flag如下:

    Intent.FLAG_ACTIVITY_NEW_TASK

    这个Flag跟我们的singleInstance很相似:在给目标Activity设立此Flag后,会根据目标Activity的affinity进行匹配:如果已经存在与其affinity相同的task,则将目标Activity压入此Task。    反之没有的话,则新建一个task,新建的task的affinity值与目标Activity相同。然后将目标Activity压入此栈。

    其实简单来说,就是先看看需不需要创建一个新的Task,根据就是有没有相同的affinity。然后把Activity放进去。

    但是此情况和singleInstance有不同,有两点注意的地方:

    1. 新的Task没有说只能存放一个目标Activity。只是说决定是否新建一个Task。而singleInstance模式下新的Task只能放置一个目标Activity。
    2. 在同一应用下,如果Activity都是默认的affinity,那么此Flag无效。而singleInstance默认情况也会创建新的Task。

    这个东西理解起来可能有一些抽象,我们通过一个实例来证明他:

    在之前的一些例子中,我们都是在同一应用之间进行跳转,而现在我们进行不同App的Activity相互跳转(其实就是创造一个不同taskAffinity的情况。。。忘了的话见一、4)。

    首先,我们需要创建一个新的App——TwoApp,这个App目前只需要一个MainActivity就够了,我们在MainActivity放置一个button,让他跳转到OneApp的TwoActivity。

    public void onClick(View v) {
        Intent intent = new Intent("ONETEXT_TWOACTIVITY");
        
        startActivity(intent);
    }

    这是跳转的代码。

    现在我们先概述一下我们的流程:我们先打开TwoApp,然后在TwoApp的MainActivity界面跳转到OneApp的TwoActivity。

    对于OneApp的设定,我们已经将三个Activity都设置成了standard模式。还是1->2,2->3,3->2。

    代码就不上了,这么简单,大家自己也能写出来。效果如下:

    为了看的清清楚楚,最开始清空了所有的进程。

    现在我们点开TwoApp,

    现在只有TwoApp一个进程,

    现在我们点开了 OneApp的TwoActivity,但是我们发现他还是只有一个进程,


    现在我们在TwoApp的MainActivity跳转到OneApp的TwoActivity,添加_NEW_TASK的Flag。

    public void onClick(View v) {
        Intent intent = new Intent("ONETEXT_TWOACTIVITY");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    我们再看一下效果,还是跟刚才一样先清空所有的进程,这次效果直接连起来看了:


    与上面不同的地方在于,我们新的界面创建在了新的进程中——其实就是OneApp被唤醒了,我们来分析一下为什么会这样:

    首先我们会想一下我们上面所学过的一个东西,affinity:我们说这个东西在默认情况下就是App的包名packageName,而OneApp中的TwoActivity默认的affinity就是OneApp的包名。这里能够理解吧。

    然后我们说_NEW_TASK情况下,会先查找是否有对应的affinity的task,如果有就不在创建,直接将其放入,反之新建task,所以新建的task就是我们的OneApp的task,我们可以再做一个测试,我们先唤醒OneApp,然后再让TwoApp跳转到OneApp的TwoActivity(有点绕啊。。。),我们看是什么情况:

    首先启动OneApp,并跳转到ThreeActivity。

    然后启动TwoApp,并跳转到OneApp的TwoActivity。

    然后一直点击Back,

    我们发现在Two中唤醒One的TwoActivity,同样是被放入了OneApp的默认Task中。

    关于_NEW_TASK我们就说这么多吧。

    2.2._SINGLE_TOP

    该模式比较简单,对应Flag如下:

    Intent.FLAG_ACTIVITY_SINGLE_TOP

    次Flag与静态设置中的singleTop效果相同,所以请见二、2.

    2.3._CLEAR_TOP

    这个模式对应的Flag如下:

    Intent.FLAG_ACTIVITY_CLEAR_TOP

    当设置此Flag时,目标Activity会检查Task中是否存在此实例,如果没有则添加压入栈,

    如果有,就将位于Task中的对应Activity其上的所有Activity弹出栈,此时有以下两种情况:

    • 如果同时设置Flag_ACTIVITY_SINGLE_TOP,则直接使用栈内的对应Activity,
    • 没有设置。。。。。。。,则将栈内的对应Activity销毁重新创建。

    关于这个Flag,我们发现他和singleTask很像,准确的说,是在_CLEAR_TOP和_SINGLE_TOP同时设置的情况下,就是singleTask模式。

    而唯一不同的一点就在于:他会销毁已存在的目标实例,再重新创建。这个我们通过打印一下生命周期就好。

    这次我们只用OneApp就好了,还是1->2,2->3,3->2,这次我们将2的Flag设置为_CLEAR_TOP,看一下TwoActivity的生命周期。


    我们的流程如下:1->2       2->3    3->2     2->3    3->2    back    back   然后就退出了,这说明在Task内2上面的3的确被弹出栈了。

    然后我们再看一下2的日志:


    我想在日志图片上面标注的很清楚了,我只截取了一部分日志,我们质疑3->2时候先销毁,后创建。


    好,现在我们同时加上_SINGLE_TOP的Flag。

    效果相同,我们只看log:


    很明显,在3->2的时候,TwoActivity调用了onRestart方法,也就是栈顶复用了。

    这个Flag过。


    其实还有一点点东西想提一下的,但是感觉 篇幅已经很恶心了。。。。再写下去可能更没人看了吧/笑着哭,所以决定找机会穿插到下一篇文章中:Activity标签中task相关属性

    喜欢的话可以关注一波,有建议和不同观点的欢迎下方留言!感谢大家的支持!

    展开全文
  • Activity启动流程简述

    万次阅读 2019-04-21 00:25:06
    Activity 中发起 =====> @Override public void startActivity(Intent intent, @Nullable Bundle options) { if (options != null) { startActivityForResult(intent, -1, options); } else { ...

    在Activity 中发起

    =====>

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }
    

     

    ==>startActivityForReult()

    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
    
        // code...........
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
        //  code.......;
            }
           //code........
    }
    

     

    ===>然后进入到Instrumentation调用其execStartActivity()方法,其内部通过ActivityManager.getService()获取一个IBinder对象,然后在通过这个对象获取一个IActivityManager代理对象。通过IBinder机制去调用ActivityManagerService方法

    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
       //code......
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

     

    ====ActivitymanagerService.startActivity()===>ActivitymanagerService.startActivityAsUser()

    @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
    }
    

     

     

    ===>ActivityStarter.startActivityMayWait()==》ActivityStarter.startActivityLocked()

    final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, WaitResult outResult,
            Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask, String reason) {
    
          //code......
    final ActivityRecord[] outRecord = new ActivityRecord[1];
    int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
            aInfo, rInfo, voiceSession, voiceInteractor,
            resultTo, resultWho, requestCode, callingPid,
            callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
            options, ignoreTargetSecurity, componentSpecified, outRecord, container,
            inTask, reason);
    
    Binder.restoreCallingIdentity(origId);

    //code........

    
      }
    int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask, String reason) {
    
        if (TextUtils.isEmpty(reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        mLastStartReason = reason;
        mLastStartActivityTimeMs = System.currentTimeMillis();
        mLastStartActivityRecord[0] = null;
    
        mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
                aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
                callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
                container, inTask);
    
        if (outActivity != null) {
            // mLastStartActivityRecord[0] is set in the call to startActivity above.
            outActivity[0] = mLastStartActivityRecord[0];
        }
        return mLastStartActivityResult;
    }

     

     

     

    ===>然后还是startActivity()

    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
                String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
                String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
                ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
                ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
                TaskRecord inTask) {

        //...code

      校验权限以及解析配置文件的一些信息,并保存到ActivityRecord中去

    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
            callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
            resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
            mSupervisor, checkedOptions, sourceRecord);

        //...code

    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
            true /* doResume */, checkedOptions, inTask, outActivity);
    }

    ==》继续startActivity()

    private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
        int result = START_CANCELED;
        try {
            mService.mWindowManager.deferSurfaceLayout();
            result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
                    startFlags, doResume, options, inTask, outActivity);
        } finally {
          .....code
        }
    
        postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord,
                mTargetStack);
    
        return result;
    }
    

     

    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
            ActivityRecord[] outActivity) {
         //code.......
    if (dontStart) {
        // For paranoia, make sure we have correctly resumed the top activity.
        topStack.mLastPausedActivity = null;
        if (mDoResume) {
            mSupervisor.resumeFocusedStackTopActivityLocked();
        }
        ActivityOptions.abort(mOptions);
        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
            // We don't need to start a new activity, and the client said not to do
            // anything if that is the case, so this is it!
            return START_RETURN_INTENT_TO_CALLER;
        }
    

    ====>mSupervisor.resumeFocusedStackTopActivityLocked();这个方法是ActivityStackSuperviso类中的,主要功能可以理解为根据栈顶的Activity情况来处理将要打开的Activity

     

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        } else if (r.state == RESUMED) {
            // Kick off any lingering app transitions form the MoveTaskToFront operation.
            mFocusedStack.executeAppTransition(targetOptions);
        }
        return false;
    }
    

     

    ===》ActivityStack.resumeTopActivityUncheckedLocked()==ActivityStack.

    resumeTopActivityInnerLocked()主要根据栈顶Activity的情况来处理想要打开的Activity

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    
    
    // If the top activity is the resumed one, nothing to do.
    //如果当前栈顶的Activity是想要打开的Activity并且处于Resume,就啥也不需要做了,结束了
    if (mResumedActivity == next && next.isState(RESUMED)
            && mStackSupervisor.allResumedActivitiesComplete()) {
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        executeAppTransition(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Top activity resumed " + next);
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return false;
    }
    
    // If we are sleeping, and there is no resumed activity, and the top
    // activity is paused, well that is the state we want.
    //或者,如果系统休眠+栈顶是想要打开的Activity则也啥也不用处理
    if (shouldSleepOrShutDownActivities()
            && mLastPausedActivity == next
            && mStackSupervisor.allPausedActivitiesComplete()) {
        // Make sure we have executed any pending transitions, since there
        // should be nothing left to do at this point.
        executeAppTransition(options);
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Going to sleep and all paused");
        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
        return false;
    }
    //将栈顶的Activity给pause掉(pause掉就得栈顶Activity)
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);
        pausing |= startPausingLocked(userLeaving, false, next, false);
    }

    code............

    //然后在打开新的Activity(新的生命周期)

    mStackSupervisor.startSpecificActivityLocked(next, true, false);
    
    }

    //到这里大致就结束了。但是上面的两个分流有必要看看:旧Activity的pause和新的Activity的开启

     

    一:旧的Activity的onPause

    ActivityStack.startPauseinglocked()===>PauseActivityItem.execute()====>ActivityThread.handlepauseActivity

    ActivityStack:
    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean pauseImmediately) {
    //code.....................
      if (prev.app != null && prev.app.thread != null) {
        if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
        try {
            EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                    prev.userId, System.identityHashCode(prev),
                    prev.shortComponentName);
            mService.updateUsageStats(prev, false);
            prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                    userLeaving, prev.configChangeFlags, pauseImmediately);
      //code..................
    }

    ==========>ActivityThread.schedulePauseActivity(),在主线程里面通过Handle发送一个消息PAUSE_ACTIVITY====> 然后执行handlePauseActivity()

    public final void schedulePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        int seq = getLifecycleSeq();
        if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
                + " operation received seq: " + seq);
        sendMessage(
                finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                token,
                (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                configChanges,
                seq);
    }
    
    case PAUSE_ACTIVITY: {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
        SomeArgs args = (SomeArgs) msg.obj;
        handlePauseActivity((IBinder) args.arg1, false,
                (args.argi1 & USER_LEAVING) != 0, args.argi2,
                (args.argi1 & DONT_REPORT) != 0, args.argi3);
        maybeSnapshot();
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    } break;
    private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
        ActivityClientRecord r = mActivities.get(token);
       //code.......................
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
    
            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }
    
       //code......................
            mSomeActivitiesChanged = true;
        }
    }
    
    final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState, String reason) {
        if (r.paused) {
    
           //code.........................
    ///加了一个锁    保证所有执行onPasued 的方法可以 串行,最后执行onPause
        // Notify any outstanding on paused listeners
        ArrayList<OnActivityPausedListener> listeners;
        synchronized (mOnPauseListeners) {
            listeners = mOnPauseListeners.remove(r.activity);
        }
        int size = (listeners != null ? listeners.size() : 0);
        for (int i = 0; i < size; i++) {
            listeners.get(i).onPaused(r.activity);
        }
    
        return !r.activity.mFinished && saveState ? r.state : null;
    }

    注意:之前旧的版本的这块操作是通过发送ON_PAUSE的消息来执行来执行,新的则是通过回调

     

    二:新的Activity的启动

    mStackSupervisor.startSpecificActivityLocked()==mStackSupervisor.realStartActivityLocked()==>
    LaunchActivityItem.execute()==>ActivityThread.handleLaunchActivity()
    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
    
    code.......
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,        System.identityHashCode(r), r.info,
            // TODO: Have this take the merged configuration instead of separate global and
            // override configs.
            mergedConfiguration.getGlobalConfiguration(),
            mergedConfiguration.getOverrideConfiguration(), r.compat,
            r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
            r.persistentState, results, newIntents, !andResume,
            mService.isNextTransitionForward(), profilerInfo);

    //code..........................

    }

    =========>ActivityThread.scheduleLaunchActivity()  然后H发送LAUNCH_ACTIVITY消息===》执行ActivityThread.performLaunchActivity()方法

    @Override
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
            CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
            int procState, Bundle state, PersistableBundle persistentState,
            List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
            boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
    
        updateProcessState(procState, false);
    
        ActivityClientRecord r = new ActivityClientRecord();
    
        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.referrer = referrer;
        r.voiceInteractor = voiceInteractor;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
        r.persistentState = persistentState;
    
        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;
    
        r.startsNotResumed = notResumed;
        r.isForward = isForward;
    
        r.profilerInfo = profilerInfo;
    
        r.overrideConfig = overrideConfig;
        updatePendingConfiguration(curConfig);
    
        sendMessage(H.LAUNCH_ACTIVITY, r);
    }
    
    
    case LAUNCH_ACTIVITY: {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
    
        r.packageInfo = getPackageInfoNoCheck(
                r.activityInfo.applicationInfo, r.compatInfo);
        handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    } break;
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        // If we are getting ready to gc after going to the background, well
        // code............................................
       //1.这个方法主要是attach()+oncre()+onstart()
        Activity a = performLaunchActivity(r, customIntent);
    
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
    
            if (!r.activity.mFinished && r.startsNotResumed) {
            //2.调用onResume方法
                performPauseActivityIfNeeded(r, reason);        
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
    //code..................................
        }
    }

    1.先看performLaunchActivity()方法:先通过反射获取Activity,然后调用attach()方法常见PhoneWindow以及DectorViewe最后在调用onCreate()和onStart()生命周期

     

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");
    
       //通过反射获取将要打开的Activity
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }
    
        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
                Window window = null;
                if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                    window = r.mPendingRemoveWindow;
                    r.mPendingRemoveWindow = null;
                    r.mPendingRemoveWindowManager = null;
                }
                appContext.setOuterContext(activity);
          // 调用attach()方法,创建PhoneWindow以及DectorView,mContentParent(就是咱们setContentView的布局)并给Activity的顶层传递UiThread 等这里就不细说了
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
    
                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
               //设置Activity的主题Theme
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }
             activity.mCalled = false;
           //这里便是调用onCreate()方法了
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
    //
                    activity.performStart();
                    r.stopped = false;
                }
                //code................................
        }
    
        return activity;
    }

    .调用 mInstrumentation.callActivityOnCreate()===activity.onCre()

    activity.mCalled = false;
    if (r.isPersistable()) {
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    

    Instrumentation.callActivityOnCreate()==>activity.performCreate()==actiivty.create();

    最终调用了onCre方法,这里面通过setContent(int reslayout),得到一个布局资源文件,然后用XmlResourceParser解析,并添加进contentParent中供后面渲染使用

    
     

     

    public void callActivityOnCreate(Activity activity, Bundle icicle,
            PersistableBundle persistentState) {
        prePerformCreate(activity);
        activity.performCreate(icicle, persistentState);
        postPerformCreate(activity);
    }
    final void performCreate(Bundle icicle) {
        restoreHasCurrentPermissionRequest(icicle);
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }
    
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
    
        if (getApplicationInfo().targetSdkVersion > O && mActivityInfo.isFixedOrientation()) {
            final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window);
            final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta);
            ta.recycle();
    
          //code.................................
        getApplication().dispatchActivityCreated(this, savedInstanceState);
        if (mVoiceInteractor != null) {
            mVoiceInteractor.attachActivity(this);
        }
        mCalled = true;
    }

    onStart()和onCreate()所以就不看了

    注意:getApplication().dispatchActivityCreated(this, savedInstanceState);Activity的每个生命周期调用的时候 ,将当前的activity传递给APPlication,并调用的对应其生命周期的回调。所以实现只要实现Application的 registerActivityLifecycleCallbacks(ActivityLifecycleCallbackscallback)回调方法,可以监听每个加载进来的Activity 及其对应的生命周期。我们可以进行任务栈或者特殊功能的实现。

    2.在看看ActivityThread.handleResumeActivity()方法:主要是将DectotView放到PhoneWindow里面去,通过RootViewImp进行onMeasure()  onlayout ()  onDraw(),正好与之前的一个博客接上

    final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
            return;
        }
    
      
        if (r != null) {
            final Activity a = r.activity;
          
            final int forwardBit = isForward ?
                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;
    
            boolean willBeVisible = !a.mStartedActivity;
            if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManager.getService().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
    //将DectorView添加进去PhoneWIndow  进行测量  布局  渲染 并展示出来
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (r.mPreserveWindow) {
                    a.mWindowAdded = true;
                    r.mPreserveWindow = false;
                    // Normally the ViewRoot sets up callbacks with the Activity
                    // in addView->ViewRootImpl#setView. If we are instead reusing
                    // the decor view we have to notify the view root that the
                    // callbacks may have changed.
                    ViewRootImpl impl = decor.getViewRootImpl();
                    if (impl != null) {
                        impl.notifyChildRebuilt();
                    }
                }
                if (a.mVisibleFromClient) {
                    if (!a.mWindowAdded) {
                        a.mWindowAdded = true;
                        wm.addView(decor, l);
                    } else {
                        // The activity will get a callback for this {@link LayoutParams} change
                        // earlier. However, at that time the decor will not be set (this is set
                        // in this method), so no action will be taken. This call ensures the
                        // callback occurs with the decor set.
                        a.onWindowAttributesChanged(l);
                    }
                }
    
            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
            } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }
    
            // Get rid of anything left hanging around.
            cleanUpPendingRemoveWindows(r, false /* force */);
    
            // The window is now visible if it has been added, we are not
            // simply finishing, and we are not starting another activity.
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                if (r.newConfig != null) {
                    performConfigurationChangedForActivity(r, r.newConfig);
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                            + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
                    r.newConfig = null;
                }
                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                        + isForward);
                WindowManager.LayoutParams l = r.window.getAttributes();
                if ((l.softInputMode
                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                        != forwardBit) {
                    l.softInputMode = (l.softInputMode
                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                            | forwardBit;
                    if (r.activity.mVisibleFromClient) {
                        ViewManager wm = a.getWindowManager();
                        View decor = r.window.getDecorView();
                        wm.updateViewLayout(decor, l);
                    }
                }
    到这里Activity的流程就结束了,还是挺多的。
            
    

     

     

     

    
     
    展开全文
  • Activity的四种启动方式

    千次阅读 2018-02-28 17:17:05
    Activity的四种启动模式 Android开发者在AndroidManifest文件中一共设计了四种启动模式 standard singleTop singleTask singleInstance 一、Android 任务栈 在了解Acvitity的四种启动模式之前,我们必须...
  • 一张图搞定,Activity启动流程

    千次阅读 2018-07-24 15:17:42
    秋招开始了啊,盼了好久,所以现在面临我的是!明显笔试比不过刷算法的→找内推又不认识人→苦心找到了→...接着上次聊聊Activity的生命周期,onSaveInstanceState/onRestoreInstanceState源码分析,继续聊Activit...
  • Activity启动流程比较复杂, 涉及的类及代码都很多, 本文侧重从整体流程描述这个过程,给出关键节点,尽量少的涉及代码细节。 啥也不说了,先上图。 在看本文的内容时, 可以参照此图片进行阅读。 ...
  • Activity启动过程详解

    千次阅读 2015-11-05 12:52:49
    如何启动一个Activity?当我们调用startActivity()或startActivityForResult()后是如何启动Activity的?Activity的启动模式分析
  • 在Android系统中,Activity和Service是应用程序的核心组件,它们以松藕合的方式组合在一起构成了一个完整的应用程序,这得益于应用程序框架层提供了一套完整的机制来协助应用程序启动这些Activity和Service,以及...
  • Android Activity启动模式的设置

    千次阅读 2013-11-02 11:22:28
    Android为了使我们能够打破默认的堆栈的先后出的模式,提供了两个种方式:一种是在AndroidManifest.xml定义Activity时指定它的加载模式,另一种是在用Intent开启一个Activity时,在Intent中加入标志。如果两种方式都...
  • Android 8.0 Activity启动流程分析

    千次阅读 2020-01-18 15:33:13
    Activity启动过程中需要注意的一些类: Instrumentation 完成对Application和Activity初始化和生命周期调用的工具类。用来监控系统与应用的交互。 ActivityThread 管理应用进程的主线程的执行。 ...
  • activity启动模式笔记

    千次阅读 2015-03-01 21:40:17
    activity启动模式的逻辑主要在startActivityUncheckedLocked()函数中,现在来看下这个函数。 final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession...
  • 当我开始阅读Android 8.0源码时发现应用程序(根Activity)启动过程照Android 7.0有了一些变化,因此又写下了本篇文章,本篇文章照此前...由于篇幅较长,Android8.0 根Activity启动过程仍旧分为前篇和后篇来进行讲解。
  • Android Activity启动流程分析

    千次阅读 2018-04-17 11:29:20
    概述 Activity作为Android的四大组件之一,Android主要的界面组成部分,用于直接跟用户进行交互操作,在面试中与...启动Activity的方式大致有两种:一种是在桌面点击应用程序的图标,进入应用程序的主界面;另一...
  • Android源码解析之(十四)-->Activity启动流程

    万次阅读 多人点赞 2016-04-23 19:17:31
    好吧,终于要开始讲解Activity启动流程了,Activity启动流程相对复杂一下,涉及到了Activity中的生命周期方法,涉及到了Android体系的CS模式,涉及到了Android中进程通讯Binder机制等等,首先介绍一下Activity,...
  • 前言 熟悉Activity的启动流程和运行原理是一个合格的应用开发人员所应该具备的基本素质,...本文基于Android 9.0版本源码,从Activity启动方法startActivity为切入口分析整个流程。 一、发出启动请求 启动一个A...
  • Activity启动流程源码分析
  • 深入理解Activity启动流程(一)--Activity启动的概要流程深入理解Activity启动流程(二)--Activity启动相关类的类图深入理解Activity启动流程(三)--Activity启动的详细流程2深入理解Activity启动流程(四)--Activity ...
  • Android Activity启动过程

    2018-08-20 20:52:51
    在Android系统中,有两种操作会引发Activity的启动,一种用户点击应用程序图标时,Launcher会为我们启动应用...应用程序的默认Activity启动起来后,它又可以在内部通过调用startActvity接口启动新的Activity,依...
  • Activity启动过程涉及到的比较多的知识点有Binder的跨进程通讯,建议先看完Binder的跨进程通讯再来阅读本篇文章,在文章阅读开始,我们先要理解Activity启动模型,再者去理解有关Activity启动的基本概念,梳理...
  • 安卓Activity启动模式 1.1 两种启动方式 1. 在AndroidMainfest.xml中启动 例如: AndroidMainfest.xml.xml中设置Activity的launchMode=“singleTop” 有singleInstance,singleTask,singleTop,standard四种可选 2...
  • 深入理解Activity启动流程

    千次阅读 2016-04-14 09:54:13
    深入理解Activity启动流程(一)–Activity启动相关类的类图 Activity启动时的概要交互流程 用户从Launcher程序点击应用图标可启动应用的入口Activity,Activity启动时需要多个进程之间的交互,Android系统中...
  • Android四大组件之Activity启动流程源码实现详解(二)

    千次阅读 热门讨论 2020-09-27 22:02:54
          Activity启动流程源码实现详解(二) Android四大组件源码实现详解系列博客目录: Android应用进程创建流程大揭秘 Android四大组件之bindService源码实现详解 Android四大组件之Activity启动流程源码实现...
  • Activity启动模式与任务栈(Task)全面深入记录(下)

    万次阅读 多人点赞 2016-07-30 12:28:42
    http://blog.csdn.net/javazejian/article/details/52072131  通过上一篇文件的分析,我们对Activity的启动模式有了比较清晰的了解后,本篇我们将继续对Activity启动模式的相关参数和任务栈分析,接下来我们就...
  • Android中任务栈(task)的作用,activity启动模式,FLAG_ACTIVITY_NEW_TASK标记的含义,taskAffinity属性的作用
  • Activity启动模式 及 Intent Flags 与 栈 的关联分析

    万次阅读 多人点赞 2014-05-10 18:44:14
    在学习Android的过程中,Intent是我们最常用Android用于进程内或进程间通信的机制,其底层的通信是以Binder机制实现的,在物理层则是通过共享内存的方式实现的。  Intent主要用于2种情景下:(1)发起意图 ...
  • android 面试Activity启动流程

    千次阅读 2018-07-18 18:27:20
    市场上对Activity启动这块分析的文章很多,但是面试过程中简短的描述就需要很熟悉源码并且用精炼的语言描述出来。先看下大佬是怎么回答这个问题的: Activity的启动过程,我们可以从Context的startAct...
  • Activity 启动模式及常见启动Flag总结

    千次阅读 2018-11-08 23:33:29
    Activity 4种启动模式: 1、android:launchMode=”standard” 标准启动模式。这种启动模式也是Activity默认的,一个栈中可以有多个相同的Activity。不会考虑是否栈中是否有相同的Activity。比如设置A为standard模式...
  • 优化Activity启动速度的另类解法

    千次阅读 2018-07-29 12:48:45
    今天来给大家分享一个性能优化的经验,主要在Activity启动方面。 众所周知,给用户即时的响应是增强移动设备用户体验的重要一环,而Activity在启动过程中,又会经历至少onCreate(), onStart(), onResume()这三个回...
  • android:Activity启动模式之singleInstance

    千次阅读 2016-02-14 14:22:38
    只有一个实例,并且这个实例独立运行在一个activity任务栈中,这个task只有这个实例,不允许有别的Activity存在下面我们通过一个实例来了解singleInstance启动模式 在手机上的运行结果如下图 layout布局文件为 ...

空空如也

1 2 3 4 5 ... 20
收藏数 921,346
精华内容 368,538
关键字:

activity启动