Activity 啓動過程全解析

Activity啓動過程


一些基本的概念

  • ActivityManagerServices,簡稱AMS,服務端對象,負責系統中所有Activity的生命週期
  • ActivityThread,App的真正入口。當開啓App之後,會調用main()開始運行,開啓消息循環隊列,這就是傳說中的UI線程或者叫主線程。與ActivityManagerServices配合,一起完成Activity的管理工作
  • ApplicationThread,用來實現ActivityManagerService與ActivityThread之間的交互。在ActivityManagerService需要管理相關Application中的Activity的生命週期時,通過ApplicationThread的代理對象與ActivityThread通訊。
  • ApplicationThreadProxy,是ApplicationThread在服務器端的代理,負責和客戶端的ApplicationThread通訊。AMS就是通過該代理與ActivityThread進行通信的。
  • Instrumentation,每一個應用程序只有一個Instrumentation對象,每個Activity內都有一個對該對象的引用。Instrumentation可以理解爲應用進程的管家,ActivityThread要創建或暫停某個Activity時,都需要通過Instrumentation來進行具體的操作。
  • ActivityStack,Activity在AMS的棧管理,用來記錄已經啓動的Activity的先後關係,狀態信息等。通過ActivityStack決定是否需要啓動新的進程。
  • ActivityRecord,ActivityStack的管理對象,每個Activity在AMS對應一個* ActivityRecord,來記錄Activity的狀態以及其他的管理信息。其實就是服務器端的Activity對象的映像。
  • TaskRecord,AMS抽象出來的一個“任務”的概念,是記錄ActivityRecord的棧,一個“Task”包含若干個ActivityRecord。AMS用TaskRecord確保Activity啓動和退出的順序。如果你清楚Activity的4種launchMode,那麼對這個概念應該不陌生。

回答一些問題

zygote是什麼?有什麼作用?

zygote意爲“受精卵“。Android是基於Linux系統的,而在Linux中,所有的進程都是由init進程直接或者是間接fork出來的,zygote進程也不例外。

在Android系統裏面,zygote是一個進程的名字。Android是基於Linux System的,當你的手機開機的時候,Linux的內核加載完成之後就會啓動一個叫“init“的進程。在Linux System裏面,所有的進程都是由init進程fork出來的,我們的zygote進程也不例外。

我們都知道,每一個App其實都是

  • 一個單獨的dalvik虛擬機
  • 一個單獨的進程

所以當系統裏面的第一個zygote進程運行之後,在這之後再開啓App,就相當於開啓一個新的進程。而爲了實現資源共用和更快的啓動速度,Android系統開啓新進程的方式,是通過fork第一個zygote進程實現的。所以說,除了第一個zygote進程,其他應用所在的進程都是zygote的子進程,這下你明白爲什麼這個進程叫“受精卵”了吧?因爲就像是一個受精卵一樣,它能快速的分裂,並且產生遺傳物質一樣的細胞!

SystemServer是什麼?有什麼作用?它與zygote的關係是什麼?

首先我要告訴你的是,SystemServer也是一個進程,而且是由zygote進程fork出來的。

知道了SystemServer的本質,我們對它就不算太陌生了,這個進程是Android Framework裏面兩大非常重要的進程之一——另外一個進程就是上面的zygote進程。

爲什麼說SystemServer非常重要呢?因爲系統裏面重要的服務都是在這個進程裏面開啓的,比如
ActivityManagerService、PackageManagerService、WindowManagerService等等,看着是不是都挺眼熟的?

那麼這些系統服務是怎麼開啓起來的呢?

在zygote開啓的時候,會調用ZygoteInit.main()進行初始化

public static void main(String argv[]) {

     ...ignore some code...

    //在加載首個zygote的時候,會傳入初始化參數,使得startSystemServer = true
     boolean startSystemServer = false;
     for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            ...ignore some code...

         //開始fork我們的SystemServer進程
     if (startSystemServer) {
                startSystemServer(abiList, socketName);
         }

     ...ignore some code...

}

我們看下startSystemServer()做了些什麼

    /**留着這個註釋,就是爲了說明SystemServer確實是被fork出來的
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {

         ...ignore some code...

        //留着這段註釋,就是爲了說明上面ZygoteInit.main(String argv[])裏面的argv就是通過這種方式傳遞進來的
        /* Hardcoded command line to start the system server */
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };

        int pid;
        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        //確實是fuck出來的吧,我沒騙你吧~不對,是fork出來的 -_-|||
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

ActivityManagerService是什麼?什麼時候初始化的?有什麼作用?

ActivityManagerService,簡稱AMS,服務端對象,負責系統中所有Activity的生命週期。

ActivityManagerService進行初始化的時機很明確,就是在SystemServer進程開啓的時候,就會初始化ActivityManagerService。從下面的代碼中可以看到

public final class SystemServer {

    //zygote的主入口
    public static void main(String[] args) {
        new SystemServer().run();
    }

    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
    }

    private void run() {

        ...ignore some code...

        //加載本地系統服務庫,並進行初始化 
        System.loadLibrary("android_servers");
        nativeInit();

        // 創建系統上下文
        createSystemContext();

        //初始化SystemServiceManager對象,下面的系統服務開啓都需要調用SystemServiceManager.startService(Class<T>),這個方法通過反射來啓動對應的服務
        mSystemServiceManager = new SystemServiceManager(mSystemContext);

        //開啓服務
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }

        ...ignore some code...

    }

    //初始化系統上下文對象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);
    }

    //在這裏開啓了幾個核心的服務,因爲這些服務之間相互依賴,所以都放在了這個方法裏面。
    private void startBootstrapServices() {

        ...ignore some code...

        //初始化ActivityManagerService
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);

        //初始化PowerManagerService,因爲其他服務需要依賴這個Service,因此需要儘快的初始化
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // 現在電源管理已經開啓,ActivityManagerService負責電源管理功能
        mActivityManagerService.initPowerManagement();

        // 初始化DisplayManagerService
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

    //初始化PackageManagerService
    mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
       mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

    ...ignore some code...

    }

}

經過上面這些步驟,我們的ActivityManagerService對象已經創建好了,並且完成了成員變量初始化。而且在這之前,調用createSystemContext()創建系統上下文的時候,也已經完成了mSystemContext和ActivityThread的創建。注意,這是系統進程開啓時的流程,在這之後,會開啓系統的Launcher程序,完成系統界面的加載與顯示。

你是否會好奇,我爲什麼說AMS是服務端對象?下面我給你介紹下Android系統裏面的服務器和客戶端的概念。

其實服務器客戶端的概念不僅僅存在於Web開發中,在Android的框架設計中,使用的也是這一種模式。服務器端指的就是所有App共用的系統服務,比如我們這裏提到的ActivityManagerService,和前面提到的PackageManagerService、WindowManagerService等等,這些基礎的系統服務是被所有的App公用的,當某個App想實現某個操作的時候,要告訴這些系統服務,比如你想打開一個App,那麼我們知道了包名和MainActivity類名之後就可以打開

Intent intent = new Intent(Intent.ACTION_MAIN);  
intent.addCategory(Intent.CATEGORY_LAUNCHER);              
ComponentName cn = new ComponentName(packageName, className);              
intent.setComponent(cn);  
startActivity(intent); 

但是,我們的App通過調用startActivity()並不能直接打開另外一個App,這個方法會通過一系列的調用,最後還是告訴AMS說:“我要打開這個App,我知道他的住址和名字,你幫我打開吧!”所以是AMS來通知zygote進程來fork一個新進程,來開啓我們的目標App的。這就像是瀏覽器想要打開一個超鏈接一樣,瀏覽器把網頁地址發送給服務器,然後還是服務器把需要的資源文件發送給客戶端的。

知道了Android Framework的客戶端服務器架構之後,我們還需要了解一件事情,那就是我們的App和AMS(SystemServer進程)還有zygote進程分屬於三個獨立的進程,他們之間如何通信呢?

知道了Android Framework的客戶端服務器架構之後,我們還需要了解一件事情,那就是我們的App和AMS(SystemServer進程)還有zygote進程分屬於三個獨立的進程,他們之間如何通信呢?

App與AMS通過Binder進行IPC通信,AMS(SystemServer進程)與zygote通過Socket進行IPC通信。

那麼AMS有什麼用呢?在前面我們知道了,如果想打開一個App的話,需要AMS去通知zygote進程,除此之外,其實所有的Activity的開啓、暫停、關閉都需要AMS來控制,所以我們說,AMS負責系統中所有Activity的生命週期。

在Android系統中,任何一個Activity的啓動都是由AMS和應用程序進程(主要是ActivityThread)相互配合來完成的。AMS服務統一調度系統中所有進程的Activity啓動,而每個Activity的啓動過程則由其所屬的進程具體來完成。

這樣說你可能還是覺得比較抽象,沒關係,下面有一部分是專門來介紹AMS與ActivityThread如何一起合作控制Activity的生命週期的。

Launcher是什麼?什麼時候啓動的?

當我們點擊手機桌面上的圖標的時候,App就由Launcher開始啓動了。但是,你有沒有思考過Launcher到底是一個什麼東西?

Launcher本質上也是一個應用程序,和我們的App一樣,也是繼承自Activity

packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

public final class Launcher extends Activity
        implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
                   View.OnTouchListener {
                   }

Launcher實現了點擊、長按等回調接口,來接收用戶的輸入。既然是普通的App,那麼我們的開發經驗在這裏就仍然適用,比如,我們點擊圖標的時候,是怎麼開啓的應用呢?如果讓你,你怎麼做這個功能呢?捕捉圖標點擊事件,然後startActivity()發送對應的Intent請求唄!是的,Launcher也是這麼做的,就是這麼easy!

那麼到底是處理的哪個對象的點擊事件呢?既然Launcher是App,並且有界面,那麼肯定有佈局文件呀,是的,我找到了佈局文件launcher.xml

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
    android:id="@+id/launcher">

    <com.android.launcher2.DragLayer
        android:id="@+id/drag_layer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <!-- Keep these behind the workspace so that they are not visible when
             we go into AllApps -->
        <include
            android:id="@+id/dock_divider"
            layout="@layout/workspace_divider"
            android:layout_marginBottom="@dimen/button_bar_height"
            android:layout_gravity="bottom" />

        <include
            android:id="@+id/paged_view_indicator"
            layout="@layout/scroll_indicator"
            android:layout_gravity="bottom"
            android:layout_marginBottom="@dimen/button_bar_height" />

        <!-- The workspace contains 5 screens of cells -->
        <com.android.launcher2.Workspace
            android:id="@+id/workspace"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:paddingStart="@dimen/workspace_left_padding"
            android:paddingEnd="@dimen/workspace_right_padding"
            android:paddingTop="@dimen/workspace_top_padding"
            android:paddingBottom="@dimen/workspace_bottom_padding"
            launcher:defaultScreen="2"
            launcher:cellCountX="@integer/cell_count_x"
            launcher:cellCountY="@integer/cell_count_y"
            launcher:pageSpacing="@dimen/workspace_page_spacing"
            launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
            launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">

            <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
            <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
            <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
            <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
            <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
        </com.android.launcher2.Workspace>

    ...ignore some code...

    </com.android.launcher2.DragLayer>
</FrameLayout>

爲了方便查看,我刪除了很多代碼,從上面這些我們應該可以看出一些東西來:Launcher大量使用標籤來實現界面的複用,而且定義了很多的自定義控件實現界面效果,dock_divider從佈局的參數聲明上可以猜出,是底部操作欄和上面圖標佈局的分割線,而paged_view_indicator則是頁面指示器,和App首次進入的引導頁下面的界面引導是一樣的道理。當然,我們最關心的是Workspace這個佈局,因爲註釋裏面說在這裏麪包含了5個屏幕的單元格,想必你也猜到了,這個就是在首頁存放我們圖標的那五個界面(不同的ROM會做不同的DIY,數量不固定)。

接下來,我們應該打開workspace_screen佈局,看看裏面有什麼東東。

workspace_screen.xml

<com.android.launcher2.CellLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:paddingStart="@dimen/cell_layout_left_padding"
    android:paddingEnd="@dimen/cell_layout_right_padding"
    android:paddingTop="@dimen/cell_layout_top_padding"
    android:paddingBottom="@dimen/cell_layout_bottom_padding"
    android:hapticFeedbackEnabled="false"
    launcher:cellWidth="@dimen/workspace_cell_width"
    launcher:cellHeight="@dimen/workspace_cell_height"
    launcher:widthGap="@dimen/workspace_width_gap"
    launcher:heightGap="@dimen/workspace_height_gap"
    launcher:maxGap="@dimen/workspace_max_gap" />

裏面就一個CellLayout,也是一個自定義佈局,那麼我們就可以猜到了,既然可以存放圖標,那麼這個自定義的佈局很有可能是繼承自ViewGroup或者是其子類,實際上,CellLayout確實是繼承自ViewGroup。在CellLayout裏面,只放了一個子View,那就是ShortcutAndWidgetContainer。從名字也可以看出來,ShortcutAndWidgetContainer這個類就是用來存放快捷圖標和Widget小部件的,那麼裏面放的是什麼對象呢?

在桌面上的圖標,使用的是BubbleTextView對象,這個對象在TextView的基礎之上,添加了一些特效,比如你長按移動圖標的時候,圖標位置會出現一個背景(不同版本的效果不同),所以我們找到BubbleTextView對象的點擊事件,就可以找到Launcher如何開啓一個App了。

除了在桌面上有圖標之外,在程序列表中點擊圖標,也可以開啓對應的程序。這裏的圖標使用的不是BubbleTextView對象,而是PagedViewIcon對象,我們如果找到它的點擊事件,就也可以找到Launcher如何開啓一個App。

其實說這麼多,和今天的主題隔着十萬八千里,上面這些東西,你有興趣就看,沒興趣就直接跳過,不知道不影響這篇文章閱讀。

BubbleTextView的點擊事件在哪裏呢?我來告訴你:在Launcher.onClick(View v)裏面。

/**
     * Launches the intent referred by the clicked shortcut
     */
    public void onClick(View v) {

          ...ignore some code...

         Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            // Open shortcut
            final Intent intent = ((ShortcutInfo) tag).intent;
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1],
                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
        //開始開啓Activity咯~
            boolean success = startActivitySafely(v, intent, tag);

            if (success && v instanceof BubbleTextView) {
                mWaitingForResume = (BubbleTextView) v;
                mWaitingForResume.setStayPressed(true);
            }
        } else if (tag instanceof FolderInfo) {
            //如果點擊的是圖標文件夾,就打開文件夾
            if (v instanceof FolderIcon) {
                FolderIcon fi = (FolderIcon) v;
                handleFolderClick(fi);
            }
        } else if (v == mAllAppsButton) {
        ...ignore some code...
        }
    }

從上面的代碼我們可以看到,在桌面上點擊快捷圖標的時候,會調用

startActivitySafely(v, intent, tag);

那麼從程序列表界面,點擊圖標的時候會發生什麼呢?實際上,程序列表界面使用的是AppsCustomizePagedView對象,所以我在這個類裏面找到了onClick(View v)。

com.android.launcher2.AppsCustomizePagedView.java

/**
 * The Apps/Customize page that displays all the applications, widgets, and shortcuts.
 */
public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
        View.OnClickListener, View.OnKeyListener, DragSource,
        PagedViewIcon.PressedCallback, PagedViewWidget.ShortPressListener,
        LauncherTransitionable {

     @Override
    public void onClick(View v) {

         ...ignore some code...

        if (v instanceof PagedViewIcon) {
            mLauncher.updateWallpaperVisibility(true);
            mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
        } else if (v instanceof PagedViewWidget) {
                 ...ignore some code..
         }
     }      
   }

可以看到,調用的是

mLauncher.startActivitySafely(v, appInfo.intent, appInfo);

殊途同歸

不管從哪裏點擊圖標,調用的都是Launcher.startActivitySafely()。

下面我們就可以一步步的來看一下Launcher.startActivitySafely()到底做了什麼事情。

 boolean startActivitySafely(View v, Intent intent, Object tag) {
        boolean success = false;
        try {
            success = startActivity(v, intent, tag);
        } catch (ActivityNotFoundException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
        }
        return success;
    }

調用了startActivity(v, intent, tag)

 boolean startActivity(View v, Intent intent, Object tag) {

        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        try {
            boolean useLaunchAnimation = (v != null) &&
                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);

            if (useLaunchAnimation) {
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    startActivity(intent, opts.toBundle());
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(),
                            opts.toBundle());
                }
            } else {
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    startActivity(intent);
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(), null);
                }
            }
            return true;
        } catch (SecurityException e) {
        ...
        }
        return false;
    }

這裏會調用Activity.startActivity(intent, opts.toBundle()),這個方法熟悉嗎?這就是我們經常用到的Activity.startActivity(Intent)的重載函數。而且由於設置了

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

所以這個Activity會添加到一個新的Task棧中,而且,startActivity()調用的其實是startActivityForResult()這個方法。

@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);
        }
    }

所以我們現在明確了,Launcher中開啓一個App,其實和我們在Activity中直接startActivity()基本一樣,都是調用了Activity.startActivityForResult()。

Instrumentation是什麼?和ActivityThread是什麼關係?

還記得前面說過的Instrumentation對象嗎?每個Activity都持有Instrumentation對象的一個引用,但是整個進程只會存在一個Instrumentation對象。當startActivityForResult()調用之後,實際上還是調用了mInstrumentation.execStartActivity()

public void startActivityForResult(Intent intent, int requestCode, @Nullable 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());
            }
            ...ignore some code...    
        } else {
            if (options != null) {
                 //當現在的Activity有父Activity的時候會調用,但是在startActivityFromChild()內部實際還是調用的mInstrumentation.execStartActivity()
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
         ...ignore some code...    
    }

下面是mInstrumentation.execStartActivity()的實現

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
            ...ignore some code...
      try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .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) {
        }
        return null;
    }

所以當我們在程序中調用startActivity()的 時候,實際上調用的是Instrumentation的相關的方法。

Instrumentation意爲“儀器”,我們先看一下這個類裏面包含哪些方法吧

我們可以看到,這個類裏面的方法大多數和Application和Activity有關,是的,這個類就是完成對Application和Activity初始化和生命週期的工具類。比如說,我單獨挑一個callActivityOnCreate()讓你看看

public void callActivityOnCreate(Activity activity, Bundle icicle) {
        prePerformCreate(activity);
        activity.performCreate(icicle);
        postPerformCreate(activity);
    }

對activity.performCreate(icicle);這一行代碼熟悉嗎?這一行裏面就調用了傳說中的Activity的入口函數onCreate(),不信?接着往下看

Activity.performCreate()

final void performCreate(Bundle icicle) {
        onCreate(icicle);
        mActivityTransitionState.readState(icicle);
        performCreateCommon();
    }

沒騙你吧,onCreate在這裏調用了吧。但是有一件事情必須說清楚,那就是這個Instrumentation類這麼重要,爲啥我在開發的過程中,沒有發現他的蹤跡呢?

是的,Instrumentation這個類很重要,對Activity生命週期方法的調用根本就離不開他,他可以說是一個大管家,但是,這個大管家比較害羞,是一個女的,管內不管外,是老闆娘~

那麼你可能要問了,老闆是誰呀?
老闆當然是大名鼎鼎的ActivityThread了!

ActivityThread你都沒聽說過?那你肯定聽說過傳說中的UI線程吧?是的,這就是UI線程。我們前面說過,App和AMS是通過Binder傳遞信息的,那麼ActivityThread就是專門與AMS的外交工作的。

AMS說:“ActivityThread,你給我暫停一個Activity!”
ActivityThread就說:“沒問題!”然後轉身和Instrumentation說:“老婆,AMS讓暫停一個Activity,我這裏忙着呢,你快去幫我把這事辦了把~”
於是,Instrumentation就去把事兒搞定了。

所以說,AMS是董事會,負責指揮和調度的,ActivityThread是老闆,雖然說家裏的事自己說了算,但是需要聽從AMS的指揮,而Instrumentation則是老闆娘,負責家裏的大事小事,但是一般不拋頭露面,聽一家之主ActivityThread的安排。

如何理解AMS和ActivityThread之間的Binder通信?

前面我們說到,在調用startActivity()的時候,實際上調用的是

mInstrumentation.execStartActivity()

但是到這裏還沒完呢!裏面又調用了下面的方法

ActivityManagerNative.getDefault()
                .startActivity
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章