Activity启动分析

启动activity步骤详解
详解2

image.png

ActivityThread-attach-ams.attachApplication将AppThread传给AMS
ActivityManagerNative extends Binder??
ActivityManagerNative->asInterface->ActivityManagerProxy
ActivityThread.attach:

bindapplication参数AppBindData
launchActivity参数ActivityClientRecord
解析activity信息
startActivityLocked:保存调用者信息
unckeckLocked:检查栈信息
resumeTopActivityLokced:检查Pause信息,(看resumeActivity为不为空)
startSpecificActivityLocked:检查是否有对应的进程,fork-main-attach-准备完毕
realStartActivityLocked:ipc调 ApplicationThread.scheduleLaunchActivity-> ActivityThread.handleLaunchActivity-> ActivityThread.performLaunchActivity,参数为ActivityClientRecord
performLaunchActivity: Instrumentation.newActivity: 加载新类,即创建Activity对象;
2) ActivityClientRecord.packageInfo.makeApplication:创建Application对象;一般已有
Activity.attach- Instrumentation.callActivityOnCreate- ActivityThread.handleResumeActivity

AMS变量:
List<ActivityRecord> mHistory;//活动列表
List<ActivityRecord> mLRUActivitys; //最近任务列表
List<ActivityRecord> mPnedingActivityLaunches;//pending列表
List<ActivityRecord> mStopingActivitys;//理念先启动,在停止,启动2时1先放这里,等2启动完毕,再来处理
List<ActivityRecord> mFinishingActivitys;//结束的,不回直接销毁,等内存不足才销毁。

mPausingActivity;//只有正在暂停某Activity时才有值
mResumedActivity; //前台运行的Activity,
mFocusedActivity;
mLastPausedActivity;

ProcessRecord进程信息:

Applicationinfo:
进程名
HashSet<String> pkglist;进程里的所有apk的包名
所有的activitys\provides\services

ActivityRecord

Activity对应的档案信息:
Activity的信息等、package、进程名,状态:idle\stop\finishing等

TaskRecord:

保存Activity的启动和退出信息:
int taskid; //task id
Intent intent; //创建该Task对应的intent
int numActivitys; //该task下的activity数目
TaskRecord中并没有该Task下所有的ActivityRecord列表,想要看的话需要从AMS的mHistory列表遍历查找,AMS的mHistory列表顺序是按task排的,最上面的是最前面显示的。

Instrumentation和ActivityThread的关系,类似于老板与经理的关系,老板负责对外交流(如与Activity Manager Service<AMS>),Instrumentation负责管理并完成老板交待的任务。

当ActivityThread 创建(callActivityOnCreate)、暂停、恢复某个Activity时,通过调用此对象的方法来实现,如:

  1. 创建: callActivityOnCreate
  2. 暂停: callActivityOnPause
  3. 恢复: callActivityOnResume
Instrumentation主要方法:
Instrumentation
  1. 在Android系统里面,zygote是一个进程的名字。
  2. Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。在Linux System里面,所有的进程都是由init进程fork出来的,
  3. 我们的zygote进程也不例外。
  4. SystemServer也是一个进程,是由zygote进程fork出来的。
  5. App进程也是zygote进程fork出来的

流程1:

在zygote开启的时候,会调用ZygoteInit.main()进行初始化

  1. 方法里fork了SystemServer进程:
  2. 调用startSystemServer()方法

调用SystemServer.main方法:

  1. 创建SystemServiceManager并启动各种服务
  2. 创建系统上下文mSystemContext是一个ContextImpl对象

此时:我们的ActivityManagerService对象已经创建好了,并且完成了成员变量初始化。而且在这之前,调用createSystemContext()创建系统上下文的时候,也已经完成了mSystemContext和ActivityThread的创建。

App与AMS通过Binder进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信。

关键剪口:IActivityManager
1.ActivityManagerService实现了该接口
2.本地ActivityManagerNative也实现了该接口,ActivityManagerNative拿到了ActivityManagerService的本地代理(IActivityManager对象),并包装成了ActivityManagerProxy对象。
3.所以ActivityManagerService在客户端的代理就是ActivityManagerProxy

本地调Ams:
ActivityManagerProxy:
Ams调本地:
ApplicationThreadProxy:

IApplicationThread当创建Application时,将把此Binder对象传递给AMS,然后AMS把它保存在mProcessNames.ProcessRecord.thread中。当需要通知Application工作时,则调用IApplicationThread中对应的接口函数。

ActivityManagerService端使用ActivityStack来管理系统中所有的Activities的状态,Activities使用stack的方式进行管理。它是真正负责做事的家伙,

应用的启动入口:

ActivityThread.main()方法:
    1.ooper.prepareMainLooper();
    2.ActivityThread thread = new ActivityThread();
    4.AsyncTask.init();
    5.Looper.loop();
    3.thread.attach(false);    
        1.IActivityManager mgr = ActivityManagerNative.getDefault();//AMS本地代理
        2.mgr.attachApplication(mAppThread);//ApplicationThread mAppThread = new ApplicationThread();
                                            //一个ActivityThread有一个,实现了IApplicationThread接口
                                            //这里是通过rpc调用ams的attachApplication方法
                                            //在此方法里将ApplicationThread的binder传给了AMS,这样AMS
                                            //就拿到了客户端的一个连接:ApplicationThreadProxy

            //ams服务端的attachApplication方法的
            1.attachApplicationLocked(mAppThread, callingPid);
                1.mAppThread.bindApplication//这里又会通过IPC调用到到本地的ApplicationThread的对应方法

                    //客户端的ApplicationThread的bindApplication方法
                    1.handleBindApplication//通过handler、msg调用的
                        1.mInstrumentation创建  
                        3.mInstrumentation.callApplicationOnCreate(app);    //appication oncreate
                        2.Application app = data.info.makeApplication(...)//data.info是一个LoadeApk对象

                            1.ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);//创建应用context
                            2.app = mInstrumentation.newApplication...//mInstrumentation创建application
                                 1.Application app = (Application)clazz.newInstance();
                                 2.app.attach(context); //所以是先调用的attach

Activity启动流程:

1.startActivityForResult-》
2.mInstrumentation.execStartActivity
ActivityManagerNative.getDefault().startActivity//RPC调用AMS的方法
//准备完成后 RPC调用客户端ApplicationThread.scheduleLaunchActivity
3.ApplicationThread.scheduleLaunchActivity
4.发消息调用ActivityThread.handleLaunchActivity
5.ActivityThread.performLaunchActivity

流程参考1:


流程参考1

ActivityStack.startActivityLocked:
1.处理传进来的参数caller,得到调用者的进程信息,并保存在callerApp变量中 ProcessRecord类型















主要对象功能介绍

我们下面的文章将围绕着这几个类进行介绍。可能你第一次看的时候,印象不深,不过没关系,当你跟随者我读完这篇文章的时候,我会在最后再次列出这些对象的功能,相信那时候你会对这些类更加的熟悉和深刻。

  1. ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期
  2. ActivityThread,App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作
  3. ApplicationThread,用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯。
  4. ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的。
  5. Instrumentation,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作。
  6. ActivityStack,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程。
  7. ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像。
  8. TaskRecord,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。如果你清楚Activity的4种launchMode,那么对这个概念应该不陌生。




每一个App其实都是

  1. 一个单独的dalvik虚拟机
  2. 一个单独的进程
    所以当系统里面的第一个zygote进程运行之后,在这之后再开启App,就是通过fork第一个zygote进程实现的。所以说,除了第一个zygote进程,其他应用所在的进程都是zygote的子进程。这下你明白为什么这个进程叫“受精卵”了吧?



//初始化系统上下文对象mSystemContext,并设置默认的主题,mSystemContext实际上是一个ContextImpl对象。调用ActivityThread.systemMain()的时候,会调用ActivityThread.attach(true),而在attach()里面,则创建了Application对象,并调用了Application.onCreate()。
private void createSystemContext() {
    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}






Launcher启动app参考1

/***************************************************************** 
 * Launcher通过Binder告诉ActivityManagerService, 
 * 它将要启动一个新的Activity; 
 ****************************************************************/  
Launcher.startActivitySafely->    
Launcher.startActivity->    
 //要求在新的Task中启动此Activity    
 //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)    
 Activity.startActivity->    
 Activity.startActivityForResult->    
 Instrumentation.execStartActivity->    
  // ActivityManagerNative.getDefault()返回AMS Proxy接口    
  ActivityManagerNative.getDefault().startActivity->    
  ActivityManagerProxy.startActivity->    
    
   ActivityManagerService.startActivity-> (AMS)    
   ActivityManagerService.startActivityAsUser->     
    
    ActivityStack.startActivityMayWait->    
    ActivityStack.resolveActivity(获取ActivityInfo)    
      //aInfo.name为main Activity,如:com.my.test.MainActivity    
      //aInfo.applicationInfo.packageName为包名,如com.my.test    
    ActivityStack.startActivityLocked->    
      //ProcessRecord callerApp; 调用者即Launcher信息    
      //ActivityRecord sourceRecord; Launcher Activity相关信息    
      //ActivityRecord r=new ActivityRecord(...),将要创建的Activity相关信息      
    ActivityStack.startActivityUncheckedLocked->    
     //Activity启动方式:ActivityInfo.LAUNCH_MULTIPLE/LAUNCH_SINGLE_INSTANCE/    
     //             ActivityInfo.LAUNCH_SINGLE_TASK/LAUNCH_SINGLE_TOP)    
     // 创建一个新的task,即TaskRecord,并保存在ActivityRecord.task中    
     //r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true)    
     // 把新创建的Activity放在栈顶       
     ActivityStack.startActivityLocked->    
     ActivityStack.resumeTopActivityLocked->    
     ActivityStack.startPausingLocked (使Launcher进入Paused状态)->      
  
     /***************************************************************** 
      * AMS通过Binder通知Launcher进入Paused状态 
      ****************************************************************/  
      ApplicationThreadProxy.schedulePauseActivity->     
      //private class ApplicationThread extends ApplicationThreadNative    
      ApplicationThread.schedulePauseActivity->    
    
       ActivityThread.queueOrSendMessage->    
     
       // 调用Activity.onUserLeaveHint    
       // 调用Activity.onPause    
       // 通知activity manager我进入了pause状态    
       ActivityThread.handlePauseActivity->    
  
       /***************************************************************** 
        * Launcher通过Binder告诉AMS,它已经进入Paused状态 
        ****************************************************************/  
       ActivityManagerProxy.activityPaused->    
       ActivityManagerService.activityPaused->    
       ActivityStack.activityPaused->(把Activity状态修改为PAUSED)    
       ActivityStack.completePauseLocked->    
      
       // 参数为代表Launcher这个Activity的ActivityRecord    
       // 使用栈顶的Activity进入RESUME状态    
       ActivityStack.resumeTopActivityLokced->    
         //topRunningActivityLocked将刚创建的放于栈顶的activity取回来    
         // 即在ActivityStack.startActivityUncheckedLocked中创建的    
  
       /***************************************************************** 
        * AMS创建一个新的进程,用来启动一个ActivityThread实例, 
        * 即将要启动的Activity就是在这个ActivityThread实例中运行 
        ****************************************************************/  
       ActivityStack.startSpecificActivityLocked->    
    
        // 创建对应的ProcessRecord    
        ActivityManagerService.startProcessLocked->    
            
         // 启动一个新的进程    
         // 新的进程会导入android.app.ActivityThread类,并且执行它的main函数,    
         // 即实例化ActivityThread, 每个应用有且仅有一个ActivityThread实例    
         Process.start("android.app.ActivityThread",...)->    
  
         // 通过zygote机制创建一个新的进程    
         Process.startViaZygote->    
      
         // 这个函数在进程中创建一个ActivityThread实例,然后调用    
         // 它的attach函数,接着就进入消息循环    
         ActivityThread.main->    
  
         /***************************************************************** 
          * ActivityThread通过Binder将一个ApplicationThread类的Binder对象 
          * 传递给AMS,以便AMS通过此Binder对象来控制Activity整个生命周期 
          ****************************************************************/  
         ActivityThread.attach->    
         IActivityManager.attachApplication(mAppThread)->    
         ActivityManagerProxy.attachApplication->    
         ActivityManagerService.attachApplication->    
    
         // 把在ActivityManagerService.startProcessLocked中创建的ProcessRecord取出来    
         ActivityManagerService.attachApplicationLocked->    
  
         /***************************************************************** 
          * AMS通过Binder通知ActivityThread一切准备OK,它可以真正启动新的Activity了 
          ****************************************************************/              
         // 真正启动Activity    
         ActivityStack.realStartActivityLocked->    
         ApplicationThreadProxy.scheduleLaunchActivity->    
         ApplicationThread.scheduleLaunchActivity->    
         ActivityThread.handleLaunchActivity->    
           // 加载新的Activity类,并执行它的onCreate    
           ActivityThread.performLaunchActivity    
            /*1) Instrumentation.newActivity: 加载新类,即创建Activity对象;  
              2) ActivityClientRecord.packageInfo.makeApplication:创建Application对象;  
                 <LoadedApk.makeApplication>  
              3) Activity.attach(Context context, ActivityThread aThread,  
                    Instrumentation instr, IBinder token, int ident,  
                    Application application, Intent intent, ActivityInfo info,  
                    CharSequence title, Activity parent, String id,  
                    NonConfigurationInstances lastNonConfigurationInstances,  
                    Configuration config):把Application attach到Activity, 即把Activtiy  
                                           相关信息设置到新创建的Activity中  
              4) Instrumentation.callActivityOnCreate:调用onCreate;*/    
      
           // 使用Activity进入RESUMED状态,并调用onResume    
           ActivityThread.handleResumeActivity    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容