Activity啟動流程

概述

Android中啟動某個Activity,將先啟動Activity所在的應用。應用啟動時會啟動一個以應用包名為進程名的進程,該進程有一個主線程,叫ActivityThread,也叫做UI線程。
本系列博客將詳細闡述Activity的啟動流程。

Activity啟動時的概要交互流程
用戶從Launcher程序點擊應用圖標可啟動應用的入口Activity,Activity啟動時需要多個進程之間的交互,Android系統(tǒng)中有一個zygote進程專用于孵化Android框架層和應用層程序的進程。還有一個system_server進程,該進程里運行了很多binder service,例如ActivityManagerService,PackageManagerService,WindowManagerService,這些binder service分別運行在不同的線程中,其中ActivityManagerService負責管理Activity棧,應用進程,task。
Activity啟動時的概要交互流程如下圖如下所示

activity_start_flow

用戶在Launcher程序里點擊應用圖標時,會通知ActivityManagerService啟動應用的入口Activity,ActivityManagerService發(fā)現(xiàn)這個應用還未啟動,則會通知Zygote進程孵化出應用進程,然后在這個dalvik應用進程里執(zhí)行ActivityThread的main方法。應用進程接下來通知ActivityManagerService應用進程已啟動,ActivityManagerService保存應用進程的一個代理對象,這樣ActivityManagerService可以通過這個代理對象控制應用進程,然后ActivityManagerService通知應用進程創(chuàng)建入口Activity的實例,并執(zhí)行它的生命周期方法。

Activity啟動相關類的類圖

在介紹Activity的詳細啟動流程之前,先為大家介紹Activity啟動時涉及到的類,這樣大家可以有大概的了解,不至于在細節(jié)中迷失。
Activity啟動時涉及到的類有

  • IActivityManager相關類
  • IApplicationThread相關類
  • ActivityManagerService相關類

IActivityManager相關類

IActivityManager

Activity的管理采用binder機制,管理Activity的接口是IActivityManager。
ActivityManagerService實現(xiàn)了Activity管理功能,位于system_server進程,ActivityManagerProxy對象是ActivityManagerService在普通應用進程的一個代理對象,應用進程通過ActivityManagerProxy對象調用ActivityManagerService提供的功能。
應用進程并不會直接創(chuàng)建ActivityManagerProxy對象,而是通過調用ActiviyManagerNative類的工具方法getDefault方法得到ActivityManagerProxy對象。所以在應用進程里通常這樣啟動Activty:

ActivityManagerNative.getDefault().startActivity()

IApplicationThread相關類

IApplicationThread

應用進程需要調用ActivityManagerService提供的功能,而ActivityManagerService也需要主動調用應用進程以控制應用進程并完成指定操作。這樣ActivityManagerService也需要應用進程的一個Binder代理對象,而這個代理對象就是ApplicationThreadProxy對象。

ActivityManagerService通過IApplicationThread接口管理應用進程,ApplicationThread類實現(xiàn)了IApplicationThread接口,實現(xiàn)了管理應用的操作,ApplicationThread對象運行在應用進程里。ApplicationThreadProxy對象是ApplicationThread對象在ActivityManagerService線程 (ActivityManagerService線程運行在system_server進程)內的代理對象,ActivityManagerService通過ApplicationThreadProxy對象調用ApplicationThread提供的功能,比如讓應用進程啟動某個Activity。

ActivityManagerService相關類

ActivityManagerService

ActivityManagerService管理Activity時,主要涉及以下幾個類:

  • 1 ActivityManagerService,它是管理activity的入口類,聚合了ProcessRecord對象和ActivityStack對象
  • 2 ProcessRecord,表示應用進程記錄,每個應用進程都有對應的ProcessRecord對象
  • 3 ActivityStack,該類主要管理回退棧
  • 4 ActivityRecord,每次啟動一個Actvity會有一個對應的ActivityRecord對象,表示Activity的一個記錄
  • 5 ActivityInfo,Activity的信息,比如啟動模式,taskAffinity,flag信息(這些信息在AndroidManifest.xml里聲明Activity時填寫)
  • 6 TaskRecord,Task記錄信息,一個Task可能有多個ActivityRecord,但是一個ActivityRecord只能屬于一個TaskRecord

注意:

ActivityManagerService里只有一個ActivityStack對象,并不會像Android官方文檔描述的一樣,每個Task都有一個activity stack對象。ActivityStack管理ActivityRecord時,不是下面這樣組織ActivityRecord的:

List<TaskRecord> taskList; //ActivityStack類
List<ActivityRecord> recordList;// TaskRecord類

而是像下面這樣組織ActivityRecord:

ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>(); //ActivityStack類里
TaskRecord task; // ActivityRecord類里

也就是說ActivityManagerService組織回退棧時以ActivityRecord為基本單位,所有的ActivityRecord放在同一個ArrayList里,可以將mHistory看作一個棧對象,索引0所指的對象位于棧底,索引mHistory.size()-1所指的對象位于棧頂。

但是ActivityManagerService調度ActivityRecord時以task為基本單位,每個ActivityRecord對象都屬于某個TaskRecord,一個TaskRecord可能有多個ActivityRecord。

ActivityStack沒有TaskRecord列表的入口,只有在ActivityManagerService才有TaskRecord列表的入口:

final ArrayList<TaskRecord> mRecentTasks

ActivityStack管理ActivityRecord時,將屬于同一個task的ActivityRecord放在一起,如下所示:

backstack

回退棧里可看到兩個task,假設上面的task為task1,下面的task為task2,task1包含D,E兩個Activity Record,task2包含3個ActivityRecord。task1位于回退棧的棧頂,task2位于task1下面,task1中E位于棧頂,task2中C位于棧頂。需注意兩個task的Activity不會混在一起,也就是說task2的B不能放在task1的D和E中間。
因為回退棧是棧結構,所以此時不斷按返回鍵,顯示的Activity的順序為E–>D–>C–>B–>A。

Activity啟動的詳細流程

1. Activity調用ActivityManagerService啟動應用
2. ActivityManagerService調用Zygote孵化應用進程
3. Zygote孵化應用進程
4. 新進程啟動ActivityThread
5. 應用進程綁定到ActivityManagerService
6. ActivityThread的Handler處理啟動Activity的消息

1. Activity調用ActivityManagerService啟動應用

activity_amservice

在launcher應用程序里啟動應用時,點擊應用圖標后,launcher程序會調用startActivity啟動應用,傳遞的intent參數:

intent = new Intent(Intent.ACTION_MAIN);
   intent.addCategory(Intent.CATEGORY_LAUNCHER);
   intent.setComponent(className);

activity最終調用Instrumentation的execStartActivity來啟動應用:

//Activity類
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
 if (mParent == null) {
    Instrumentation.ActivityResult ar =
                    mInstrumentation.execStartActivity(
                        this, mMainThread.getApplicationThread(), mToken, this,
                        intent, requestCode, options);
       if (ar != null) {
                    mMainThread.sendActivityResult(
                        mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                        ar.getResultData());
       } 
    //...   
 }else{
  //...
 }

Instrumentation調用ActivityManagerProxy對象的startActivity方法啟動Activity,而ActivityManagerProxy只是ActivityManagerService對象在應用進程的一個代理對象,ActivityManagerProxy最終調用ActivityManagerService的startActvity方法啟動Activity。

//Instrumentation類
public ActivityResult execStartActivity(
          Context who, IBinder contextThread, IBinder token, Activity target,
          Intent intent, int requestCode, Bundle options) {
//...
 try{          
   //...
   int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, null, options);
   } catch (RemoteException e) {
   }   
//...   
}

2. ActivityManagerService調用Zygote孵化應用進程

amservice_zygote

ActivityManagerProxy對象調用ActivityManagerService對象(運行在system_server進程)的startActivity方法以啟動應用,startActivity方法接下來調用startActivityAsUser方法以啟動應用。在startActivityAsUser方法里會調用ActivityStack的startActivityMayWait方法以啟動應用,startActivityMayWait方法里啟動應用時,需先根據intent在系統(tǒng)中找到合適的應用的activity,如果有多個activity可選擇,則會彈出ResolverActivity讓用戶選擇合適的應用。

//ActivityStack類
final int startActivityMayWait(IApplicationThread caller, int callingUid,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
            Bundle options, int userId) {
//…
//根據intent在系統(tǒng)中找到合適的應用的activity,如果有多個activity可選擇,
//則會彈出ResolverActivity讓用戶選擇合適的應用。
  ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                profileFile, profileFd, userId);
//…
int res = startActivityLocked(caller, intent, resolvedType,
                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
                    startFlags, options, componentSpecified, null);
//…
}

在startActivityLocked方法里,對傳過來的參數做一些校驗,然后創(chuàng)建ActivityRecord對象,再調用startActivityUncheckedLocked方法啟動Activity。

startActivityUncheckedLocked方法負責調度ActivityRecord和Task,理解該方法是理解Actvity啟動模式的關鍵。

startActivityUncheckedLocked方法調度task的算法非常復雜,和當前回退棧,要啟動的acitivity的啟動模式以及taskAffinity屬性,啟動activity時設置的intent的flag等諸多要素相關,intent的flag就有很多種情況,故此算法非常復雜,需要閱讀源碼并結合特定啟動情況才能理解。

后續(xù)會介紹startActivityUncheckedLocked方法的實現(xiàn),并結合特定場景分析調度算法。

接下來調用startActivityLocked將ActivityRecord加入到回退棧里:

//ActivityStack類
final int startActivityUncheckedLocked(ActivityRecord r,
          ActivityRecord sourceRecord, int startFlags, boolean doResume,
          Bundle options) {
//...          
startActivityLocked(r, newTask, doResume, keepCurTransition, options);
//...
}

在startActivityLocked里調用resumeTopActivityLocked顯示棧頂Activity:

//ActivityStack類
private final void startActivityLocked(ActivityRecord r, boolean newTask,
        boolean doResume, boolean keepCurTransition, Bundle options) {
 //...        
 if (doResume) {
   resumeTopActivityLocked(null);
 }  
}

resumeTopActivityLocked(null)會調用另一個resumeTopActivityLocked方法顯示棧頂的acitivity:

//ActivityStack類
final boolean resumeTopActivityLocked(ActivityRecord prev) {
    return resumeTopActivityLocked(prev, null);
}

因為應用還未啟動過,所以調用startSpecificActivityLocked啟動應用,執(zhí)行邏輯如下:

//ActivityStack類
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
  //...
  if (next.app != null && next.app.thread != null) {
    //…
  }else{
    //…
   startSpecificActivityLocked(next, true, true);
  }
 //... 
}

在startSpecificActivityLocked里調用mService.startProcessLocked啟動應用:

//ActivityStack類
private final void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
   ProcessRecord app = mService.getProcessRecordLocked(r.processName,
              r.info.applicationInfo.uid);
   //...
   mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
        "activity", r.intent.getComponent(), false, false);
}

在ActivityManagerService的startProcessLocked方法里:

//ActivityManagerService類
final ProcessRecord startProcessLocked(String processName,
          ApplicationInfo info, boolean knownToBeDead, int intentFlags,
          String hostingType, ComponentName hostingName, boolean allowWhileBooting,
          boolean isolated) {
 ProcessRecord app;
 if (!isolated) {
     app = getProcessRecordLocked(processName, info.uid);
 } else {
     //...
 }
 //...
 if (app == null) {
    app = newProcessRecordLocked(null, info, processName, isolated);
    if (app == null) {
        Slog.w(TAG, "Failed making new process record for "
                + processName + "/" + info.uid + " isolated=" + isolated);
        return null;
    }
    mProcessNames.put(processName, app.uid, app);
    if (isolated) {
        mIsolatedProcesses.put(app.uid, app);
    }
  } else {
   //..
 }
 //...
 startProcessLocked(app, hostingType, hostingNameStr);
 //...
}

在startProcessLocked方法里:

//ActivityManagerService類
private final void startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr) {
  //...
  try {
      //...
      // Start the process.  It will either succeed and return a result containing
  // the PID of the new process, or else throw a RuntimeException.
  //Zygote孵化dalvik應用進程后,會執(zhí)行android.app.ActivityThread類的main方法
      Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
              app.processName, uid, uid, gids, debugFlags, mountExternal,
              app.info.targetSdkVersion, app.info.seinfo, null);
      //...    
  } catch (RuntimeException e) {
      //...
  }
}

在Process類的start方法里:

/Process類
public static final ProcessStartResult start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int debugFlags, int mountExternal,
                              int targetSdkVersion,
                              String seInfo,
                              String[] zygoteArgs) {
 try{                              
  startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
  }catch (ZygoteStartFailedEx ex) {
    //...
  }                    
}

在Process類的startViaZygote方法里,會計算啟動應用進程用的各個參數,然后再調用zygoteSendArgsAndGetResult方法將這些參數通過socket發(fā)送給zygote進程,zygote進程會孵化出新的dalvik應用進程,然后告訴ActivityManagerService新啟動的進程的pid。

3. Zygote孵化應用進程

zygote

zygote進程將ZygoteInit作為啟動類,會執(zhí)行它的main方法,先注冊ZygoteSocket,然后調用runSelectLoop方法,runSelectLoop方法會調用方法在ZygoteSocket上監(jiān)聽請求,如果別的進程通過ZygoteSocket請求孵化進程,則孵化進程。

runSelectLoop方法的主要代碼:

//ZygoteInit類
private static void runSelectLoopMode() throws MethodAndArgsCaller {
  //...
  while (true) {
     //...
      try {
          fdArray = fds.toArray(fdArray);
          index = selectReadable(fdArray);
      } catch (IOException ex) {
          throw new RuntimeException("Error in select()", ex);
      }
      if (index < 0) {
          throw new RuntimeException("Error in select()");
      } else if (index == 0) {
          //監(jiān)聽客戶連接請求
          ZygoteConnection newPeer = acceptCommandPeer();
          peers.add(newPeer);
          fds.add(newPeer.getFileDesciptor());
      } else {
         //若客戶發(fā)送孵化進程的請求過來,
         //此時便需要調用ZygoteConnection的runOnce方法孵化進程
          boolean done;
          done = peers.get(index).runOnce();
          if (done) {
              peers.remove(index);
              fds.remove(index);
          }
      }
  }
}

在runOnce方法里調用Zygote.forkAndSpecialize方法孵化進程,如果返回值為0表示是在孵化出來的應用進程里,此時會調用handleChildProc進行一些處理,并使用異常機制進行逃逸,會直接逃逸至ZygoteInit的main方法。

//ZygoteConnection類
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
  //...
  try {
  //...
      pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
              parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
              parsedArgs.niceName);
  } 
  //...
  try {
      if (pid == 0) {
          // in child
          IoUtils.closeQuietly(serverPipeFd);
          serverPipeFd = null;
          //handleChildProc是一個很重要的函數,在該函數里使用了異常進行逃逸
          handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
          //...  
      } else {
         //... 
      }
  } finally {
       //...
  }
}

3.1 Zygote.forkAndSpecialize

Zygote的forkAndSpecialize方法會調用nativeForkAndSpecialize方法孵化進程,nativeForkAndSpecialize是一個本地方法,它的實現(xiàn)在dalvik/vm/native/dalvik_system_Zygote.cpp里,在該cpp文件里與nativeForkAndSpecialize對應的C++方法是Dalvik_dalvik_system_Zygote_forkAndSpecialize,在該方法里會調用forkAndSpecializeCommon孵化進程,在forkAndSpecializeCommon方法里會調用fork系統(tǒng)調用創(chuàng)建進程,因為使用的是fork機制所以創(chuàng)建進程的效率比較高。

3.2 handleChildProc

handleChildProc方法主要代碼:

//ZygoteConnection類
private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws ZygoteInit.MethodAndArgsCaller {
  //...
  if (parsedArgs.runtimeInit) {
  //...
  } else {
      String className;
      try {
          //這里得到的classname實際是android.app.ActivityThread
          className = parsedArgs.remainingArgs[0];
      } catch (ArrayIndexOutOfBoundsException ex) {
          logAndPrintError(newStderr,
                  "Missing required class name argument", null);
          return;
      }
      //...
      if (parsedArgs.invokeWith != null) {
      //...
      } else {
          ClassLoader cloader;
          if (parsedArgs.classpath != null) {
              cloader = new PathClassLoader(parsedArgs.classpath,
                      ClassLoader.getSystemClassLoader());
          } else {
              cloader = ClassLoader.getSystemClassLoader();
          }
          //調用ZygoteInit.invokeStaticMain執(zhí)行android.app.ActivityThread的main方法        
          try {
              ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
          } catch (RuntimeException ex) {
              logAndPrintError(newStderr, "Error starting.", ex);
          }
      }
  }
}

ZygoteInit的invokeStaticMain方法并不會直接執(zhí)行className的main方法,而是會構造一個 ZygoteInit.MethodAndArgsCaller異常,然后拋出來,通過異常機制會直接跳轉到ZygoteInit的main方法, ZygoteInit.MethodAndArgsCaller類實現(xiàn)了Runnable方法,在run方法里會執(zhí)行要求執(zhí)行的main方法,故此跳轉到ZygoteInit的main方法后,異常會被捕獲,然后執(zhí)行方法caller.run(),這樣便會執(zhí)行android.app.ActivityThread的main方法。

ZygoteInit的invokeStaticMain方法主要代碼:

//ZygoteInit類
static void invokeStaticMain(ClassLoader loader,
        String className, String[] argv)
        throws ZygoteInit.MethodAndArgsCaller {
  //...        
  Method m;
  try {
      m = cl.getMethod("main", new Class[] { String[].class });
  } catch(//...){
  }
  //...
  throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

ZygoteInit.MethodAndArgsCaller主要代碼:

public static class MethodAndArgsCaller extends Exception
        implements Runnable {
    //...
    public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        }//...
    }
}

ZygoteInit的main方法相關代碼:

//ZygoteInit類
public static void main(String argv[]) {
  try {
      //...
  } catch (MethodAndArgsCaller caller) {
      caller.run();
  } catch (RuntimeException ex) {
      //...
  }
}

4. 新進程啟動ActivityThread

zygote_activitythread

Zygote進程孵化出新的應用進程后,會執(zhí)行ActivityThread類的main方法。在該方法里會先準備好Looper和消息隊列,然后調用attach方法將應用進程綁定到ActivityManagerService,然后進入loop循環(huán),不斷地讀取消息隊列里的消息,并分發(fā)消息。

//ActivityThread類
public static void main(String[] args) {
    //... 
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    AsyncTask.init();
    //...
    Looper.loop();
    //...
}

5. 應用進程綁定到ActivityManagerService

application_amservice

在ActivityThread的main方法里調用thread.attach(false);attach方法的主要代碼如下所示:

//ActivityThread類
private void attach(boolean system) {
    sThreadLocal.set(this);
    mSystemThread = system;
    if (!system) {
        //...
        IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
        //調用ActivityManagerService的attachApplication方法
        //將ApplicationThread對象綁定至ActivityManagerService,
        //這樣ActivityManagerService就可以
        //通過ApplicationThread代理對象控制應用進程
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            // Ignore
        }
    } else {
        //...
    }
    //... 
}

ActivityManagerService的attachApplication方法執(zhí)行attachApplicationLocked(thread, callingPid)進行綁定。

//ActivityManagerService類
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) { 
    ProcessRecord app;
    //...     
    app.thread = thread; 
    //...  
    try {
        //...
        thread.bindApplication(processName, appInfo, providers,
                app.instrumentationClass, profileFile, profileFd, profileAutoStop,
                app.instrumentationArguments, app.instrumentationWatcher, testMode,
                enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent,
                new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                mCoreSettingsObserver.getCoreSettingsLocked());
        //... 
    } catch (Exception e) {
       //...
    }
    //... 
    ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
    if (hr != null && normalMode) {
        if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                && processName.equals(hr.processName)) {
            try {
                if (mHeadless) {
                    Slog.e(TAG, "Starting activities not supported on headless device: " + hr);
                } else if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                //mMainStack.realStartActivityLocked真正啟動activity
                    didSomething = true;
                }
            } catch (Exception e) {
                //...
            }
        } else {
            //...
        }
    }
    //... 
    return true;
}

attachApplicationLocked方法有兩個重要的函數調用thread.bindApplication和mMainStack.realStartActivityLocked。thread.bindApplication將應用進程的ApplicationThread對象綁定到ActivityManagerService,也就是說獲得ApplicationThread對象的代理對象。mMainStack.realStartActivityLocked通知應用進程啟動Activity。

5.1 thread.bindApplication

thread對象其實是ActivityThread里ApplicationThread對象在ActivityManagerService的代理對象,故此執(zhí)行thread.bindApplication,最終會調用ApplicationThread的bindApplication方法,該方法的主要代碼如下所示:

//ActivityThread類
public final void bindApplication(String processName,
        ApplicationInfo appInfo, List<ProviderInfo> providers,
        ComponentName instrumentationName, String profileFile,
        ParcelFileDescriptor profileFd, boolean autoStopProfiler,
        Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
        int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode,
        boolean persistent, Configuration config, CompatibilityInfo compatInfo,
        Map<String, IBinder> services, Bundle coreSettings) {
    //...  
    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.providers = providers;
    data.instrumentationName = instrumentationName;
    data.instrumentationArgs = instrumentationArgs;
    data.instrumentationWatcher = instrumentationWatcher;
    data.debugMode = debugMode;
    data.enableOpenGlTrace = enableOpenGlTrace;
    data.restrictedBackupMode = isRestrictedBackupMode;
    data.persistent = persistent;
    data.config = config;
    data.compatInfo = compatInfo;
    data.initProfileFile = profileFile;
    data.initProfileFd = profileFd;
    data.initAutoStopProfiler = false;
    queueOrSendMessage(H.BIND_APPLICATION, data);
}

這樣調用queueOrSendMessage會往ActivityThread的消息隊列發(fā)送消息,消息的用途是BIND_APPLICATION。

這樣會在handler里處理BIND_APPLICATION消息,接著調用handleBindApplication方法處理綁定消息。

//ActivityThread類
private void handleBindApplication(AppBindData data) {
  //...  
  ApplicationInfo instrApp = new ApplicationInfo();
  instrApp.packageName = ii.packageName;
  instrApp.sourceDir = ii.sourceDir;
  instrApp.publicSourceDir = ii.publicSourceDir;
  instrApp.dataDir = ii.dataDir;
  instrApp.nativeLibraryDir = ii.nativeLibraryDir;
  LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
        appContext.getClassLoader(), false, true);
  ContextImpl instrContext = new ContextImpl();
  instrContext.init(pi, null, this);
    //... 
  if (data.instrumentationName != null) {
       //...
  } else {
       //注意Activity的所有生命周期方法都會被Instrumentation對象所監(jiān)控,
       //也就說執(zhí)行Activity的生命周期方法前后一定會調用Instrumentation對象的相關方法
       //并不是說只有跑單測用例才會建立Instrumentation對象,
       //即使不跑單測也會建立Instrumentation對象
       mInstrumentation = new Instrumentation();
  }
  //... 
  try {
     //...
     Application app = data.info.makeApplication(data.restrictedBackupMode, null);
     mInitialApplication = app;
     //...         
     try {
          mInstrumentation.onCreate(data.instrumentationArgs);
      }catch (Exception e) {
             //...
      }
      try {
           //這里會調用Application的onCreate方法
           //故此Applcation對象的onCreate方法會比ActivityThread的main方法后調用
           //但是會比這個應用的所有activity先調用
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
           //...
        }
    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

5.2 mMainStack.realStartActivityLocked

realStartActivity會調用scheduleLaunchActivity啟動activity,主要代碼:

//ActivityStack類
final boolean realStartActivityLocked(ActivityRecord r,
        ProcessRecord app, boolean andResume, boolean checkConfig)
        throws RemoteException {
    //...  
    try {
        //...
        app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                System.identityHashCode(r), r.info,
                new Configuration(mService.mConfiguration),
                r.compat, r.icicle, results, newIntents, !andResume,
                mService.isNextTransitionForward(), profileFile, profileFd,
                profileAutoStop);
        //...
    } catch (RemoteException e) {
        //...
    }
    //...    
    return true;
}

同樣app.thread也只是ApplicationThread對象在ActivityManagerService的一個代理對象而已,最終會調用ApplicationThread的scheduleLaunchActivity方法。

//ActivityThread類
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
        Bundle state, List<ResultInfo> pendingResults,
        List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
        String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
    ActivityClientRecord r = new ActivityClientRecord();
    r.token = token;
    r.ident = ident;
    r.intent = intent;
    r.activityInfo = info;
    r.compatInfo = compatInfo;
    r.state = state;
    r.pendingResults = pendingResults;
    r.pendingIntents = pendingNewIntents;
    r.startsNotResumed = notResumed;
    r.isForward = isForward;
    r.profileFile = profileName;
    r.profileFd = profileFd;
    r.autoStopProfiler = autoStopProfiler;
    updatePendingConfiguration(curConfig);
    queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}

這里調用了queueOrSendMessage往ActivityThread的消息隊列發(fā)送了消息,消息的用途是啟動Activity,接下來ActivityThread的handler便會處理該消息。

6. ActivityThread的Handler處理啟動Activity的消息

activitythread_activity

ActivityThread的handler調用handleLaunchActivity處理啟動Activity的消息,handleLaunchActivity的主要代碼如下所示:

//ActivityThread類
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //... 
    Activity a = performLaunchActivity(r, customIntent);
    if (a != null) {
        //...
        handleResumeActivity(r.token, false, r.isForward,
                !r.activity.mFinished && !r.startsNotResumed);
        //...
    } else {
        //...
    }
}

handleLaunchActivity方法里有有兩個重要的函數調用,performLaunchActivity和handleResumeActivity,performLaunchActivity會調用Activity的onCreate,onStart,onResotreInstanceState方法,handleResumeActivity會調用Activity的onResume方法.

6.1 performLaunchActivity

performLaunchActivity的主要代碼如下所示:

//ActivityThread類
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //...
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        //...
    } catch (Exception e) {
        //...
    }
    try {
        //r.packageInfo.makeApplication實際并未創(chuàng)建Application對象,
        //因為bindApplication過程已經創(chuàng)建了Application對象,
        //makeApplication方法會返回已創(chuàng)建的Application對象
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        //...         
        if (activity != null) {
            //...
            //將application對象,appContext對象綁定到新建的activity對象
            activity.attach(appContext, this, getInstrumentation(), r.token,
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config);
            //... 
            //會調用Activity的onCreate方法             
            mInstrumentation.callActivityOnCreate(activity, r.state);
            //...
            //...
            //調用Activity的onStart方法
            if (!r.activity.mFinished) {
                activity.performStart();
                r.stopped = false;
            }              
            if (!r.activity.mFinished) {
                if (r.state != null) {
                    //會調用Activity的onRestoreInstanceState方法
                    mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                }
            }
            if (!r.activity.mFinished) {
                activity.mCalled = false;
                mInstrumentation.callActivityOnPostCreate(activity, r.state);
                //...
            }
        }
        //...
    } catch (SuperNotCalledException e) {
        throw e;
    } catch (Exception e) {
        //...
    }
    return activity;
}

6.2 handleResumeActivity

handleResumeActivity的主要代碼如下所示:

//ActivityThread類
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
        boolean reallyResume) {
    //...
    //performResumeActivity最終會調用Activity的onResume方法 
    ActivityClientRecord r = performResumeActivity(token, clearHide);
    if (r != null) {
        final Activity a = r.activity;
        //... 
        //顯示界面
        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 (a.mVisibleFromClient) {
                a.mWindowAdded = true;
                wm.addView(decor, l);
            }
           //...         
        } else if (!willBeVisible) {
             //...
        }
        // Tell the activity manager we have resumed.
        if (reallyResume) {
            try {
                ActivityManagerNative.getDefault().activityResumed(token);
            } catch (RemoteException ex) {
            }
        }
    } else {
         //...
    }
}

performResumeActivity的主要代碼如下所示:

//ActivityThread類
public final ActivityClientRecord performResumeActivity(IBinder token,
        boolean clearHide) {
    ActivityClientRecord r = mActivities.get(token);
    //...
    if (r != null && !r.activity.mFinished) {
         //...
        try {
            //... 
            //會調用Activity的onResume方法 
            r.activity.performResume();
            //...
        } catch (Exception e) {
            //...
        }
    }
    return r;
}

總結Activity的概要啟動流程:

用戶在Launcher程序里點擊應用圖標時,會通知ActivityManagerService啟動應用的入口Activity,ActivityManagerService發(fā)現(xiàn)這個應用還未啟動,則會通知Zygote進程孵化出應用進程,然后在這個dalvik應用進程里執(zhí)行ActivityThread的main方法。應用進程接下來通知ActivityManagerService應用進程已啟動,ActivityManagerService保存應用進程的一個代理對象,這樣ActivityManagerService可以通過這個代理對象控制應用進程,然后ActivityManagerService通知應用進程創(chuàng)建入口Activity的實例,并執(zhí)行它的生命周期方法

現(xiàn)在也可以理解:

如果應用的組件(包括所有組件Activity,Service,ContentProvider,Receiver) 被啟動,肯定會先啟動以應用包名為進程名的進程,這些組件都會運行在應用包名為進程名的進程里,并且是在主線程里。應用進程啟動時會先創(chuàng)建Application對象,并執(zhí)行Application對象的生命周期方法,然后才啟動應用的組件。

有一種情況比較特殊,那就是為組件設置了特殊的進程名,也就是說通過android:process設置進程名的情況,此時組件運行在單獨的進程內。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容