Activity启动过程分析

一.概述

对着老罗的博客和源码自己梳理了一遍Activity的启动过程,为了方便记忆就将这个过程整理写了下来,整个启动过程涉及到的类主要有Activity,ActivityManagerService,ActivityStack, PackageManagerService,ActivityThread和ApplicationThread.涉及到的进程一般是有2个,如果是启动另外一个应用的acitiviy就有3个进程,第一个就是我们当前应用所在的进程,第二个就是ActivityManagerService所在的进程,如果有第3个就是要启动的activity所在的进程.所以整个启动过程就涉及到了Binder的通信,其中上面说的ActivityManagerService,PackageManagerService和ApplicationThread都是Binder的子类这3个就是负责整个启动过程中的进程通信的.

二.启动过程分析

整个过程其实可以理解成2个过程,第一过程就是在他们的应用进程中封装intent将要启动的activity的信息传入到ActivityManagerService中,第二个过程就是在ActivityManagerService通过PackageManagerService来验证intent信息,通过ActivityStack来管理任务栈和存储activity,通过ActivityThread的消息队列来实际操作activity的创建和生命周期的创建.
下面就先从要启动activity所在的进程开始分析
1.Activity.startActivity->startActivityForResult->mInstrumentation.execStartActivity->ActivityManagerNative.getDefault().startActivity

2.ActivitymanagerService.startActivity
从这一步开始就进入到了ActivitymanagerService所在的进程了,这ActivitymanagerService的startActivity方法中其实是通过调用ActivityStack.startActivityMayWait方法来处理逻辑.

3.ActivityStack.startActivityMayWait
这个方法首先调用PackageManagerService的resolveIntent方法来解析intent找到这个intent代表的activity信息,
然后在调用startActivityLocked方法.

4.ActivityStack.startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType,
Uri[] grantedUriPermissions,
int grantedMode, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, boolean onlyIfNeeded,
boolean componentSpecified)

首先调用ActivityStack.isInAnyStackLocked方法其实就在ActivityStack的mActivityDisplays容器中查找要启动的activity是否存在于任意一个任务栈中.
在判断从PackageManagerService中获取到的acitiviyinfo是否为null,如果为null就表示要启动的acitiviy是没有在任何的清单文件中声明过的,就会抛出异常,否则就会通过new activityrecord 创建即将要启动的Activity的相关信息,并保存在r变量中,然后在调用startActivityUncheckedLocked

5.ActivityStack .startActivityUncheckedLocked

在这个里面会获取要启动的activity的启动模式,然后根据启动模式和要启动的activity的任务栈是否存在等信息来判断要不要启动新的任务栈,然后在进入到 startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options)中

6.ActivityStack .startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options)
这个方法就判断是否要切换新的界面,要切换就调用到resumeTopActivitiesLocked方法.

7.ActivityStack .resumeTopActivitiesLocked

它首先看要启动的Activity是否就是当前处于Resumed状态的Activity,如果是的话,那就什么都不用做,直接返回就可以了;否则再看一下系统当前是否休眠状态,如果是的话,再看看要启动的Activity是否就是当前处于堆栈顶端的Activity,如果是的话,也是什么都不用做。
上面两个条件都不满足,因此,在继续往下执行之前,首先要把当处于Resumed状态的Activity推入Paused状态,然后才可以启动新的Activity。但是在将当前这个Resumed状态的Activity推入Paused状态之前,首先要看一下当前是否有Activity正在进入Pausing状态,如果有的话,当前这个Resumed状态的Activity就要稍后才能进入Paused状态了,这样就保证了所有需要进入Paused状态的Activity串行处理。调用startPausingLocked将activity进入到Paused状态

8.ActivityStack .startPausingLocked

函数首先把mResumedActivity保存在本地变量prev中。mResumedActivity就是当前处于resume状态的activity,因此,这里把当前resueme状态进程中的ApplicationThread对象取出来,通过它来通知这个Activity它要进入Paused状态了。通过调用这个ApplicationThread对象的schedulePauseActivity来通知这个activity进入Paused状态.因为startPausingLocked是在acitiviymanagerservice进程的,而当前resume状态的activity是在我们的应用进程的,所以想要从acitiviymanagerservice进程让我们应用进程的activity进入pause状态就需要用到Binder通信,而这里完成这个通信的Binder就ApplicationThread.这个ApplicationThread就是一个Binder子类定义在ActivityThread类中.就了为了帮助ActivityThread完成进程间通信的.

  1. ActivityThread . ApplicationThread . schedulePauseActivity
  1. public final class ActivityThread {  
  2.       
  3.     ......  
  4.   
  5.     private final class ApplicationThread extends ApplicationThreadNative {  
  6.           
  7.         ......  
  8.   
  9.         public final void schedulePauseActivity(IBinder token, boolean finished,  
  10.                 boolean userLeaving, int configChanges) {  
  11.             queueOrSendMessage(  
  12.                 finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,  
  13.                 token,  
  14.                 (userLeaving ? 1 : 0),  
  15.                 configChanges);  
  16.         }  
  17.   
  18.     }  
  19.   
  20. }

其实到这一步 就是到了当前处于resume状态的activity的ActivityThread也就是主线程中来了,然后schedulePauseActivity中就是通过handler将消息发送到主线程的消息队列中去了,在看下主线程的handlerH 的handmessage方法:

  1.  public void handleMessage(Message msg) {  

  2.             switch (msg.what) {     
  3.             case PAUSE_ACTIVITY:  //
  4.                 handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);  
  5.                 maybeSnapshot();  
  6.                 break;  
  7.             ......  
  8.   
  9.             }  

如果是pause_activity就调用handlePauseActivity方法.

10.ActivityThread.handlePauseActivity

最终还是调用mInstrumentation.callActivityOnPause(r.activity)来让当前activity进入到pause状态.
然后在调用ActivityManagerNative.getDefault().activityPaused(token);告诉activitymanager这个Activity已经进入Paused状态了,ActivityManagerService现在可以完成未竟的事情,即启动新的Activity了

11.activityStack.activityPausedLocked

这个方法会继续调用completePauseLocked方法来保存pauseactivity的信息,然后调用resumeTopActivitiesLocked()

12.activityStack.resumeTopActivitiesLocked

在这个方法中会拿到我们将要启动的activityrecord,然调用startSpecificActivityLocked(r),这里就将要启动的activirecord当参数传入

13.activityStack.startSpecificActivityLocked

  1. public class ActivityStack {  
  2.   
  3.     ......  
  4.   
  5.     private final void startSpecificActivityLocked(ActivityRecord r,  
  6.             boolean andResume, boolean checkConfig) {  
  7.         通过activityrecord的进程名和uid来获取进程 ,如果用户没有在xml指定默认就是包名
  8.         ProcessRecord app = mService.getProcessRecordLocked(r.processName,  
  9.             r.info.applicationInfo.uid);  
  10.   
  11.         ......  
  12.          如果拿到了进程,就直接调用realStartActivityLocked
  13.         if (app != null && app.thread != null) {  
  14.             try {  
  15.                 realStartActivityLocked(r, app, andResume, checkConfig);  
  16.                 return;  
  17.             } catch (RemoteException e) {  
  18.                 ......  
  19.             }  
  20.         }  
  21.          如果没有拿到进程,就先通过进程名创建进程
  22.         mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,  
  23.             "activity", r.intent.getComponent(), false);  
  24.     }  
  25.   
  26.   
  27.     ......  
  28.   
  29. } 

这里就有2种情况了,如果是一个进程的第一个acitiviy也就进程还没有创建的情况就会调用ams的startProcessLocked方法先去创建进程,如果是进程已经存在的就会调用activityStack.realStartActivityLocked直接去创建acitiviy.因为创建进程完也是要创建activity的所以我们这里先去看一下ams.startProcessLocked方法.

  1. ActivityManagerService .startProcessLocked(String processName,
    ApplicationInfo info, boolean knownToBeDead, int intentFlags,
    String hostingType, ComponentName hostingName, boolean allowWhileBooting))

在这个方法中会再次再次检查是否已经有以process + uid命名的进程存在,如果不存在就会创建一个ProcessRecord,在调用startProcessLocked(ProcessRecord app,
1. String hostingType, String hostingNameStr)方法.

14.ActivityManagerService .startProcessLocked(ProcessRecord app,
1. String hostingType, String hostingNameStr),在这个方法中会调用Process.start来创建一个新的进程,实际上进程的创建还要交给Zygote进程来创建的,新的进程会导入android.app.ActivityThread类,并且执行它的main函数.

15.ActivityThread .main

  1. public static final void main(String[] args) {  
  2.           
  3.         .......  
  4.   
  5.         ActivityThread thread = new ActivityThread();  
  6.         thread.attach(false);  
  7.   
  8.         ......  
  9.   
  10.         Looper.loop();  
  11.   
  12.         .......  
  13.   
  14.         thread.detach();  
  15.           
  16.         ......  
  17.     }

这个函数在进程中创建一个ActivityThread实例,然后调用它的attach函数,接着就进入消息循环了,直到最后进程退出,所以一个进程都会有一个ActivityThread实例表示主线程.函数attach最终调用了ActivityManagerService的远程接口ActivityManagerProxy的attachApplication函数,传入的参数是mAppThread,这是一个ApplicationThread类型的Binder对象

16.ActivityManagerService.attachApplication

这里最终是调用attachApplicationLocked(IApplicationThread thread,int pid)函数来处理,thread和pid都是新进程传过来的

17.ActivityManagerService.attachApplicationLocked

这个方法会通过pid拿到我们之前创建的activirecord,并且将thread等信息设置给activityrecord,然后在调用activityStack.realStartActivityLocked.

18.activityStack.realStartActivityLocked

这里最终通过app.thread进入到ApplicationThreadProxy的scheduleLaunchActivity函数中,注意,这里的第二个参数r,是一个ActivityRecord类型的Binder对象,用来作来这个Activity的token值,这里就进入新的acitiviy所在的进程然后创建对应的acitiviy了,通信就是通过这个thread来通信的

19.ActivityThread .ApplicationThread .scheduleLaunchActivity

到了这里其实还是要通过handler将要创建activity的消息发送到消息队列中,所以下面就是进入到H的handmessage中.最终调用ActivityThread .handleLaunchActivity

20.ActivityThread .handleLaunchActivity

  1. private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
  2.         ......  
  3.      创建acitiviy,并且回调onCreate方法
  4.         Activity a = performLaunchActivity(r, customIntent);  
  5.   
  6.         if (a != null) {  
  7.             r.createdConfig = new Configuration(mConfiguration);  
  8.             Bundle oldState = r.state;  
          i.   在回调onResume方法,让acitiviy进入到onResume状态
  9.             handleResumeActivity(r.token, false, r.isForward);  
  10.   
  11.             ......  
  12.         } else {  
  13.             ......  
  14.         }  
  15.     }

21.最终是调用performLaunchActivity来创建activity

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {

//得到目标activity的ComponentName对象
        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }
        Activity activity = null;
        try {
//从package中拿到目标类的类加载器
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    //通过 mInstrumentation.newActivity创建acitiviy,实际就是通过类加载器反射创建
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        } catch (Exception e) {
            ...
        }
        try {
//如果该activity的进程application不存在就通过mInstrumentation的newApplication创建一个新的application,并且调用onCreate方法,如果已经存在了就直接返回,在应用中进程是用application来表示的
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (activity != null) {
//创建一个新的Context
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                调用activity的attach方法,赋值context,Instrumentation对象
                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);
//调用activity的oncreate方法
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
            mActivities.put(r.token, r);

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {

        }
        return activity;
    }

三.总结

1 就是将intent信息送入到activitymanagerservie中,这里涉及到了跨进程通信
3-6 就是负责校验要启动的acitiviy是否有在清单文件中注册过,没有就抛出异常,有就根据启动模式和flag等信息创建出对应的ActivityRecord准备启动
7-11 这个几个步骤就在准备启动新的activity之前先将当前处于resume状态的activity进入到pause状态,这里首先要从activitymanagerservice进程将要进入pause状态的信息发送到应用进程,等acitiviy进入到pause状态以后又要从应用进程将进入pause状态完成的信息发送到activitymanagerservice进程中

12-13 这2步就拿到要启动的activityrecord,并且通过activityrecord的进程名和uid来获取进程,如果进程不存在就创建进程,要存在就直接创建acitiviy

14-17 这几步就创建一个新的进程的过程,进程的创建都是通过Zygote进程来创建的,然后每一个进程都会创建一activitythread实例

18-21 这几部就是启动新的activity的过程,它是从acitiviymanagerservie进程及nag要启动的信息发送到新的acitiviy所在的进程的,然后通过消息队列来完成acitiviy的创建.

activityt的创建和生命周期的调用都是通过mInstrumentation来统一管理的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值