Android應(yīng)用程序的啟動

Android源碼版本9.0

應(yīng)用程序的啟動

從手機屏幕點擊APP圖標(biāo)起熟嫩,APP的啟動就已經(jīng)開始了
首先:
執(zhí)行java首次啟動都要執(zhí)行的main方法開始
Android main方法存在于ActivityThread中,也就是說啟動應(yīng)用都要從ActivityThread的main方法開始

##ActivityThread
public static void main(String[] args) {
        ...
        Looper.prepareMainLooper(); //1
        long startSeq = 0;
        if (args != null) {
            for (int i = args.length - 1; i >= 0; --i) {
                if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                    startSeq = Long.parseLong(
                            args[i].substring(PROC_START_SEQ_IDENT.length()));
                }
            }
        }
        ActivityThread thread = new ActivityThread();  //2
        thread.attach(false, startSeq); //3
        ...
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
}

說一下幾個比較重要的方法 ->

  • 注釋1 -> Looper.prepareMainLooper() -> 用于應(yīng)用啟動創(chuàng)建進程唯一的UI線程
  • 注釋2 -> 把ActivityThread創(chuàng)建出來并調(diào)用attach連接
  • 注釋3 -> 啟動Looper的消息隊列

接下來看一下具體連接了什么

##ActivityThread
private void attach(boolean system, long startSeq) {
        ...
        if (!system) {
            ...
            final IActivityManager mgr = ActivityManager.getService();  //1
            try {
                mgr.attachApplication(mAppThread, startSeq);  //2
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            ...
        } else {
            ...
        }
        ...
}
  • 注釋1 -> 通過ActivityManager獲取IActivityManager机错,這個是系統(tǒng)的本地代理對象爬范,作用是應(yīng)用進程請求系統(tǒng)進程接口,為了實現(xiàn)進程間通信弱匪,這里用到的是AIDL青瀑。具體用法不再此處說明,只需要知道這能夠?qū)崿F(xiàn)進程間交互萧诫。
  • 注釋2 -> 調(diào)用attachApplication方法斥难,調(diào)用系統(tǒng)進程接口,用于連接Application

IActivityManager具體執(zhí)行方法是在ActivityManagerService帘饶,這里讓Application去和AMS連接是為了APP和系統(tǒng)綁定哑诊,更好的方便管理當(dāng)前APP。

##ActivityManagerService
public final void attachApplication(IApplicationThread thread, long startSeq) {
        synchronized (this) {
            //獲取pid
            int callingPid = Binder.getCallingPid();  //1
            //獲取uid
            final int callingUid = Binder.getCallingUid();  //2
            final long origId = Binder.clearCallingIdentity();
            //連接Application
            attachApplicationLocked(thread, callingPid, callingUid, startSeq);  //3
            Binder.restoreCallingIdentity(origId);
        }
}

attachApplication是AMS中的一個方法及刻。

  • 注釋1和2 -> 分別獲取到pid和uid(由系統(tǒng)創(chuàng)建搭儒,并分配穷当,并且是處以沒有進程使用)。
  • 注釋3 -> 可以看到pid和uid傳入到了attachApplicationLocked這個方法中淹禾。
##ActivityManagerService
private final boolean attachApplicationLocked(IApplicationThread thread,
                                                  int pid, int callingUid, long startSeq) {
        ProcessRecord app;  //1
        long startTime = SystemClock.uptimeMillis();
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);  //2
            }
        } 
        ...
        if (app.instr != null) {  //當(dāng)前進程是否正在活動
           thread.bindApplication(processName, appInfo, providers, app.instr.mClass,
                    profilerInfo, app.instr.mArguments, app.instr.mWatcher, app.instr.mUiAutomationConnection,
                    testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()),
                    app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, isAutofillCompatEnabled);   //3
        } else {
            //Application 綁定到當(dāng)前線程
            thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                    null, null, null, testMode, mBinderTransactionTrackingEnabled,
                    enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, isAutofillCompatEnabled);  //4
        }
        ...
        //檢測最可見的Activity是否在運行進程中等待,如果再則創(chuàng)建Activity
        if (mStackSupervisor.attachApplicationLocked(app)) {  //5
            didSomething = true;
        }
        ...
}
  • 注釋1 -> rocessRecord是個進程記錄類茴扁,可以看作是一個javabean铃岔,用來保存當(dāng)前進程先關(guān)的一些信息(如pid、uip峭火、ApplicationInfo等)
  • 注釋2 -> 根據(jù)pid獲取到了這個類,其實也就是獲得當(dāng)前進程的相關(guān)屬性毁习。
  • 注釋3、注釋4 -> 綁定Application到當(dāng)前進程卖丸,thread也就是IApplicationThread纺且,它是一個AIDL的接口,作用是系統(tǒng)進程請求應(yīng)用進程的接口稍浆。實現(xiàn)類是ActivityThread中的內(nèi)部類ApplicationThread载碌。
  • 注釋5 -> 開始創(chuàng)建Activity

總結(jié):App的啟動從應(yīng)用圖標(biāo)被點擊開始,首先執(zhí)行的是ActivityThread中的main方法衅枫。
1嫁艇、創(chuàng)建出進程唯一的UI線程,并啟動它的消息隊列弦撩。
2步咪、獲取IActivityManager也就是ActivityManagerService請求系統(tǒng)進程接口,通過AIDL實現(xiàn)進程間通信益楼,作用是APP連接系統(tǒng)進程猾漫,方便管理當(dāng)前APP。這樣就完成了系統(tǒng)和應(yīng)用進程的綁定感凤。

綁定Application

##ActivityThread.ApplicationThread
public final void bindApplication(String processName...boolean autofillCompatibilityEnabled) {
        ...
        setCoreSettings(coreSettings);
        AppBindData data = new AppBindData();
        data.processName = processName;  //當(dāng)前進程名字
        data.appInfo = appInfo;     //app信息
        data.providers = providers; //providers
        ...
        //最后使用Handler發(fā)送消息悯周,并攜帶AppBindData數(shù)據(jù)
        sendMessage(H.BIND_APPLICATION, data);
}

在bindApplication中,會把傳入的一系列參數(shù)封裝成一個AppBindData對象俊扭,然后通過Handler把這個對象發(fā)送出去队橙。H是ActivityThread中的內(nèi)部類,是Handler的子類萨惑。

##ActivityThread.H
public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case BIND_APPLICATION:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                AppBindData data = (AppBindData) msg.obj;
                handleBindApplication(data);  
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            ...
        }
        ...
}

handleMessage方法是H中的方法捐康,主要是用來處理消息。

##ActivityThread 
private void handleBindApplication(AppBindData data) {
        ...
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);  //1
        ...
        Application app;
        ...
        //創(chuàng)建Application
        app = data.info.makeApplication(data.restrictedBackupMode, null);  //2
        ...
        //調(diào)用Application中的onCreate方法
        mInstrumentation.callApplicationOnCreate(app);  //3
        ...
}

##LoadedApk
public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        ...
        try {
            java.lang.ClassLoader cl = getClassLoader();
            ...
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);//2
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        ...
}
            
##Instrumentation
public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);//2
        return app;
}
public void callApplicationOnCreate(Application app) {
        app.onCreate();//3
}
  • 注釋1 -> 創(chuàng)建App的上下文環(huán)境,ContextImpl是Context的子類庸蔼,getApplicationContext()中獲取到的Context其實就是ContextImpl解总。
  • 注釋2 -> 一路往下調(diào)用,發(fā)現(xiàn)Application是通過類加載器和反射創(chuàng)建的姐仅,并把Context綁定到Application花枫。
  • 注釋3 -> Application中的onCreate方法調(diào)用

總結(jié):創(chuàng)建Application步驟
1刻盐、獲取系統(tǒng)分配的pid和uid。
2劳翰、通過IApplicationThread請求當(dāng)前進程敦锌。
3、發(fā)送消息把創(chuàng)建邏輯切換到UI線程中佳簸,如果現(xiàn)在可能是在其他線程的話乙墙。
4、通過類加載器和反射創(chuàng)建Application并綁定一個上下文環(huán)境生均。
5听想、最后執(zhí)行Application中的onCreate方法完成整個Application的創(chuàng)建并初始化。

創(chuàng)建Activity

##ActivityStackSupervisor
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        ...
        if (realStartActivityLocked(activity, app,
                top == activity /* andResume */, true /* checkConfig */)) {
            didSomething = true;
        }
        ...
}

realStartActivityLocked马胧,真正開始Activity的創(chuàng)建汉买。

##ActivityStackSupervisor
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
                                          boolean andResume, boolean checkConfig) throws RemoteException {
        ...
        // 創(chuàng)建啟動Activity
        final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
                r.appToken);
        clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                System.identityHashCode(r), r.info,
                mergedConfiguration.getGlobalConfiguration(),
                mergedConfiguration.getOverrideConfiguration(), r.compat,
                r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                profilerInfo));  //添加LaunchActivityItem的回調(diào)
        // Set desired final state.
        final ActivityLifecycleItem lifecycleItem;
        if (andResume) {
            lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
        } else {
            lifecycleItem = PauseActivityItem.obtain();
        }
        clientTransaction.setLifecycleStateRequest(lifecycleItem);
        // 通過生命周期管理對象ClientLifecycleManager,來管理Activity的生命周期狀態(tài)
        mService.getLifecycleManager().scheduleTransaction(clientTransaction);
        ...
        return true;
}

##ClientLifecycleManager
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        //ClientTransaction是個javabean 實現(xiàn)了Parcelable 序列化佩脊。
        //schedule()方法內(nèi)部蛙粘,會回調(diào)到ActivityThread.ApplicationThread的scheduleTransaction()方法
        transaction.schedule();
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }
}

##ActivityThread.ApplicationTread
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        //ActivityThread.this 指的是父類ClientTransactionHandler
        ActivityThread.this.scheduleTransaction(transaction);
}

##ClientTransactionHandler
void scheduleTransaction(ClientTransaction transaction) {
        transaction.preExecute(this);
        //發(fā)送Handler消息
        sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

執(zhí)行這一系列的方法后,會發(fā)送一條消息邻吞,在ActivithThread中處理组题。

##ActivityThread.H
public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            ...
            case EXECUTE_TRANSACTION:
                final ClientTransaction transaction = (ClientTransaction) msg.obj;
                //開始執(zhí)行
                mTransactionExecutor.execute(transaction);
                if (isSystem()) {
                    // Client transactions inside system process are recycled on the client side
                    // instead of ClientLifecycleManager to avoid being cleared before this
                    // message is handled.
                    transaction.recycle();
                }
                // TODO(lifecycler): Recycle locally scheduled transactions.
                break;
                ...
        }
        ...
}

##TransactionExecutor
public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
        executeCallbacks(transaction);  //1
        executeLifecycleState(transaction);  //5
        mPendingActions.clear();
        log("End resolving transaction");
}
public void executeCallbacks(ClientTransaction transaction) {
        final List<ClientTransactionItem> callbacks = transaction.getCallbacks();  //2
        ...
        for (int i = 0; i < size; ++i) {
            final ClientTransactionItem item = callbacks.get(i);  //3
            ...
            item.execute(mTransactionHandler, token, mPendingActions);  //4
            ...
        }
}

##LaunchActivityItem
@Override
public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        ...
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);//5
        ...
}
  • 注釋1 -> 執(zhí)行回調(diào)。
  • 注釋2 -> 獲取到ClientTransaction中的ClientTransactionItem集合抱冷。
  • 注釋3 -> 處理回調(diào),這里獲取到的ClientTransactionItem是LaunchActivityItem崔列。
  • 注釋4 -> 調(diào)用LaunchActivityItem中的execute方法。
  • 注釋5 -> 發(fā)送一個創(chuàng)建Activity的消息旺遮,ClientTransactionHandler其實就是ActivityThread,這是它的子類赵讯。 LaunchActivityItem可以把它理解成隊列中等待創(chuàng)建的Activity實例,說白了就是最終調(diào)用的位置是在ActivityThread的handleLaunchActivity方法中去處理耿眉。
##ActivityThread
public Activity handleLaunchActivity(ActivityClientRecord r,
                                         PendingTransactionActions pendingActions, Intent customIntent) {
        ...
        //開始執(zhí)行Activity的創(chuàng)建
        final Activity a = performLaunchActivity(r, customIntent);
        ...
        return a;
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ActivityInfo aInfo = r.activityInfo;   //1
        ...
        ContextImpl appContext = createBaseContextForActivity(r);   //2
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();   //3
            activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);  //4
           ...
        } catch (Exception e) {
           ...
        }
        ...
        //調(diào)用Activity的OnCreate()方法
        if (r.isPersistable()) {
            mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);   //5
        } else {
            mInstrumentation.callActivityOnCreate(activity, r.state);   
        }
        ...
        return activity;
}

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

##Activity
final void performCreate(Bundle icicle) {
        performCreate(icicle, null);
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
        mCanEnterPictureInPicture = true;
        restoreHasCurrentPermissionRequest(icicle);
        //onCreate 生命周期方法被調(diào)用
        if (persistentState != null) {
            onCreate(icicle, persistentState);
        } else {
            onCreate(icicle);
        }
        ...
}
  • 注釋1 -> 獲取Activity的信息边翼。
  • 注釋2 -> 獲取Activity的上下文環(huán)境。
  • 注釋3 -> 獲取類加載器鸣剪。
  • 注釋4 -> 通過類加載器和反射創(chuàng)建出一個Activity组底。
  • 注釋5 -> 調(diào)用Activity的onCreate方法。到這里就完成了一個Activity的創(chuàng)建筐骇。

總結(jié):Activity的創(chuàng)建
1债鸡、前期先做好Activity創(chuàng)建前的一系列相關(guān)環(huán)境配置
2、依然是通過ActivityThread的Handler把需要創(chuàng)建Activity的消息發(fā)送過去并把對應(yīng)的申請放入到ClientTransaction隊列當(dāng)中铛纬。
3厌均、最終消息會回到ActivityThread的handleLaunchActivity方法中去處理,在里面完成Activity的創(chuàng)建步驟告唆。

  • 獲取Activity的信息
  • 獲取Activity的上下文環(huán)境
  • 獲取類加載器
  • 通過類加載器和反射創(chuàng)建出一個Activity
  • 調(diào)用Activity的onCreate方法棺弊。到這里就完成了一個Activity的創(chuàng)建
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末晶密,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子模她,更是在濱河造成了極大的恐慌稻艰,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侈净,死亡現(xiàn)場離奇詭異连锯,居然都是意外死亡,警方通過查閱死者的電腦和手機用狱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拼弃,“玉大人夏伊,你說我怎么就攤上這事挽牢∪笈” “怎么了颠印?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵夕膀,是天一觀的道長轴脐。 經(jīng)常有香客問我咧擂,道長宫患,這世上最難降的妖魔是什么麦到? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任振惰,我火速辦了婚禮歌溉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘骑晶。我一直安慰自己痛垛,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布桶蛔。 她就那樣靜靜地躺著匙头,像睡著了一般。 火紅的嫁衣襯著肌膚如雪仔雷。 梳的紋絲不亂的頭發(fā)上蹂析,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音碟婆,去河邊找鬼电抚。 笑死,一個胖子當(dāng)著我的面吹牛脑融,可吹牛的內(nèi)容都是我干的喻频。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼肘迎,長吁一口氣:“原來是場噩夢啊……” “哼甥温!你這毒婦竟也來了锻煌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤姻蚓,失蹤者是張志新(化名)和其女友劉穎宋梧,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體狰挡,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡捂龄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了加叁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倦沧。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖它匕,靈堂內(nèi)的尸體忽然破棺而出展融,到底是詐尸還是另有隱情,我是刑警寧澤豫柬,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布告希,位于F島的核電站,受9級特大地震影響烧给,放射性物質(zhì)發(fā)生泄漏燕偶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一础嫡、第九天 我趴在偏房一處隱蔽的房頂上張望指么。 院中可真熱鬧,春花似錦驰吓、人聲如沸涧尿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姑廉。三九已至,卻和暖如春翁涤,著一層夾襖步出監(jiān)牢的瞬間桥言,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工葵礼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留号阿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓鸳粉,卻偏偏與公主長得像扔涧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容