App啟動(dòng)——Activity的啟動(dòng)流程

App啟動(dòng)簡單流程描述

  • 在手機(jī)上點(diǎn)擊App的快捷圖標(biāo)萤衰,此時(shí)手機(jī)屏幕就是一個(gè)Activity堕义,而這個(gè)Activity所在的APP,業(yè)界稱為launchActivity
  • 當(dāng)我們自己開發(fā)一款A(yù)PP的時(shí)候脆栋,AndvoidManifest一般會(huì)這么寫來啟動(dòng)默認(rèn)Activity
        <activity
            android:name=".login.LuanchActivity"
            android:screenOrientation="portrait"
            android:theme="@style/SplashAppTheme"
            android:windowSoftInputMode="stateAlwaysHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
  • Launch中為每個(gè)App圖標(biāo)提供了啟動(dòng)這個(gè)App所需要的Intent信息,這些信息是App安裝或者啟動(dòng)的時(shí)候倦卖,PackManagerService從自己的apk包的Manifest文件中讀取到的,所以點(diǎn)擊圖標(biāo)就會(huì)啟動(dòng)了自己的app的引導(dǎo)頁或者首頁

App啟動(dòng)流程

我們會(huì)發(fā)現(xiàn):Launcher和自己的APP(假設(shè)App名為為測試),它們位于不同的進(jìn)程中椿争,它們之間的通信是通過Binder完成——這時(shí)候ActivityManagerService(AMS)就起到了至關(guān)重要

以啟動(dòng)demo為例怕膛,整體流程分為7個(gè)階段

  • 1.Launcher通知AMS,要啟動(dòng)測試App,而且指定要啟動(dòng)App的哪個(gè)頁面(也就是AndvoidManifest中設(shè)置的首頁)
  • 2.AMS通知Launcher,"好了秦踪,我知道了嘉竟,沒你什么事情了“,同時(shí)記住要啟動(dòng)的首頁
  • 3.Launcher當(dāng)前頁面進(jìn)入Paused狀態(tài)洋侨,通知AMS,“我睡了倦蚪,你可以去找測試App了”
  • 4.AMS檢查測試App是否已經(jīng)啟動(dòng)希坚,是,則喚起測試App即可陵且,否裁僧,就要啟動(dòng)一個(gè)新的進(jìn)程,AMS在新的進(jìn)程創(chuàng)建一個(gè)ActiivtyThread,啟動(dòng)其中的main函數(shù)
  • 5.測試App啟動(dòng)后慕购,通知AMS聊疲,“我啟動(dòng)好了”
  • 6.AMS找到第二步存放的值,告訴測試APP沪悲,啟動(dòng)哪個(gè)頁面
  • 7.測試App啟動(dòng)首頁获洲,創(chuàng)建context并與首頁Activity關(guān)聯(lián),然后調(diào)用Activity的onCreate方法

至此啟動(dòng)流程完成殿如,可分成兩部分:第1~3階段贡珊,Launcher和AMS相互通信;第4~7階段涉馁,測試App和AMS相互通信

Activity啟動(dòng)流程源碼(源碼是API25)

第一階段:Launcher通知AMS

  • 第1步和第2步—點(diǎn)擊圖標(biāo)啟動(dòng)APP:點(diǎn)擊Launcher上的測試APP的快捷圖標(biāo)门岔,這時(shí)候會(huì)調(diào)用Launcher的startActIvitySafely方法,其實(shí)還是會(huì)調(diào)用Activity的startActivity方法,intent中帶著要啟動(dòng)測試App所需要的如下關(guān)鍵信息:
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" 
cmp="com.test.activity.LaunchActivity"

我們看Activity中的startActivity方法

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

startActivityForResult的源碼

   public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
        startActivityForResult(intent, requestCode, null);
    }

requestCode為-1烤送,表示Launcher并不關(guān)心測試App是否啟動(dòng)成功返回的結(jié)果

  • 第三步:startActivityForResult寒随,對(duì)上面代碼繼續(xù)往下走
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
              Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
   //...代碼省略       
    }

我們可以看到有個(gè)mMainThread的變量,這是一個(gè)ActivityThread類型的變量,

ActivityThread,就是主線程,也就是UI線程妻往,它是在App啟動(dòng)時(shí)創(chuàng)建的互艾,它代表了App應(yīng)用程序。而Application實(shí)際只是整個(gè)ActivityThread的上下文

這里需要注意兩個(gè)參數(shù):mMainThread.getApplicationThread(),和mToken
1.通過ActivityThread中的getApplicationThread方法取到一個(gè)binder對(duì)象,這個(gè)對(duì)象的類型為ApplicationThread蒲讯,代表launcher所在的APP進(jìn)程

2.mToken也是一個(gè)Binder對(duì)象忘朝,代表Launcher這個(gè)Activity也通過mInstrumentation傳遞給AMS,AMS一查就知道誰像AMS發(fā)送請(qǐng)求

這兩個(gè)參數(shù)是伏筆判帮,傳遞給AMS局嘁,以后AMS想反過來通知Launcher,就能通過這兩個(gè)參數(shù)找到Launcher晦墙。

  • 第四步悦昵,Instrumentation.execStartActivity源碼分析(Instrumentation可以幫我們找到我們要啟動(dòng)的activity)
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
     //...代碼省略
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            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) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

實(shí)際做的就是借助Instrumentation,把Activity數(shù)據(jù)傳遞給ActivityManagerNative(AMN)

  • 第五步AMN的getDefault方法(API26以后是getService,并且沒有AMN的代理對(duì)象ActivityManagerProxy)
    static public IActivityManager getDefault() {
        return gDefault.get();
    }
   private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
}

ServiceManager是一個(gè)容器類晌畅,AMN通過getDefault方法但指,從ServiceManager獲得一個(gè)對(duì)象

IBinder b = ServiceManager.getService("activity")

然后把它封裝成一個(gè)ActivityMangerProxy對(duì)象(AMP)
IActivityManager是一個(gè)實(shí)現(xiàn)了IInterface的接口,里面定義了四大組件所有的生命周期和常用方法抗楔,比如startActivity棋凳。

  • 第六步——AMP的startActivity方法。
    public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeString(callingPackage);
        intent.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(resultTo);
        data.writeString(resultWho);
        data.writeInt(requestCode);
        data.writeInt(startFlags);
        if (profilerInfo != null) {
            data.writeInt(1);
            profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
        } else {
            data.writeInt(0);
        }
        if (options != null) {
            data.writeInt(1);
            options.writeToParcel(data, 0);
        } else {
            data.writeInt(0);
        }
        mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
    }

實(shí)際就是寫數(shù)據(jù)到另一個(gè)進(jìn)程,也就是AMS连躏,然后等待AMS返回結(jié)果
第二階段:AMS處理Launcher傳過來的信息
接著上面剩岳,看上面AMP的startActivity源碼

  • Binder(也就是AMN/AMP)和AMS通信,當(dāng)啟動(dòng)自己的APP的時(shí)候會(huì)將會(huì)發(fā)送類型START_ACTIVITY請(qǐng)求給AMS入热, 同時(shí)告訴AMS啟動(dòng)哪個(gè)Activity
  • AMS會(huì)去檢查自己App中的Manmifest文件拍棕,是否存在要啟動(dòng)的APP,如果不存在勺良,就拋出Activity Not found錯(cuò)誤
  • AMS通知Launcher绰播,“沒你什么事情了,你休息吧”

AMS通過ApplicationThreadProxy發(fā)送消息尚困,而App端則通過ApplicationThread來接收這個(gè)消息蠢箩。

第三階段:Launcher去休眠,然后通知AMS:“我真的已經(jīng)睡了”
接下來將是一頓操作去尋找代碼,我只貼主要的流程代碼,首先由上面分析我們可以知道最終到的是ActivityManagerService中的startActivity方法

   @Override
    public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
    }

    @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null);
    }

    final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int startFlags,
            ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
            Bundle bOptions, boolean ignoreTargetSecurity, int userId,
            IActivityContainer iContainer, TaskRecord inTask) {
            
            // PackageManagerService-----> 掃描app事甜,注冊(cè)組件

            ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
            // Collect information about the target of the Intent.
            ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);

            rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);

            int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
                    aInfo, rInfo, voiceSession, voiceInteractor,
                    resultTo, resultWho, requestCode, callingPid,
                    callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
                    options, ignoreTargetSecurity, componentSpecified, outRecord, container,
                    inTask);
     }

     final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
            TaskRecord inTask) {
            
            // 驗(yàn)證intent忙芒、Class、Permission等
            // 保存將要啟動(dòng)的Activity的Record
            err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                    true, options, inTask);
            return err;
      }

      private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
            // 檢查將要啟動(dòng)的Activity的launchMode和啟動(dòng)Flag
            // 根據(jù)launcheMode和Flag配置task
            final boolean dontStart = top != null && mStartActivity.resultTo == null
                && top.realActivity.equals(mStartActivity.realActivity)
                && top.userId == mStartActivity.userId
                && top.app != null && top.app.thread != null
                && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
                || mLaunchSingleTop || mLaunchSingleTask);
            // 舉一個(gè)例子 SingleTop
            if (dontStart) {
                top.deliverNewIntentLocked(
                    mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);

               // Don't use mStartActivity.task to show the toast. We're not starting a new activity
               // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
               mSupervisor.handleNonResizableTaskIfNeeded(
                    top.task, preferredLaunchStackId, topStack.mStackId);
           
               return START_DELIVERED_TO_TOP;
            }

            mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
            if (mDoResume) {
                   //看這個(gè)
                  mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
      }

ActivityStackSupervirsor

    boolean resumeFocusedStackTopActivityLocked() {
        return resumeFocusedStackTopActivityLocked(null, null, null);
    }
    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
        if (targetStack != null && isFocusedStack(targetStack)) {
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
        if (r == null || r.state != RESUMED) {
            mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
        }
        return false;
    }

實(shí)際調(diào)用的是ActivityStack的resumeTopActivityUncheckedLocked

    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        //代碼省略
        boolean result = false;
        try {
          //代碼省略
            result = resumeTopActivityInnerLocked(prev, options);
        } 
        return result;
    }
    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
      //代碼省略
       if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, next, dontWaitForPause);
        }
  }
   final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
            ActivityRecord resuming, boolean dontWait) {
      if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
              //主要這個(gè)
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            } catch (Exception e) {
                // 代碼省略
            }
        } 
    }

prev.app.thread實(shí)際是ActivityThread也就是說實(shí)際調(diào)用的是ActivityThread中的schedulePauseActivity方法

   public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            int seq = getLifecycleSeq();
            if (DEBUG_ORDER) Slog.d(TAG, "pauseActivity " + ActivityThread.this
                    + " operation received seq: " + seq);
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? USER_LEAVING : 0) | (dontReport ? DONT_REPORT : 0),
                    configChanges,
                    seq);
        }

ApplicationThread(APT)接受到AMS消息后讳侨,調(diào)用ActivityThread的sendMessage方法呵萨,向Launcher的主線程消息隊(duì)列發(fā)送一個(gè)PAUSE_ACTIVITY消息

我們都知道Hnadler會(huì)調(diào)用handlerMessager,繼續(xù)走

        public void handleMessage(Message msg) {
                case PAUSE_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handlePauseActivity((IBinder) args.arg1, false,
                            (args.argi1 & USER_LEAVING) != 0, args.argi2,
                            (args.argi1 & DONT_REPORT) != 0, args.argi3);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
}

handlePauseActivity源碼

 private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport, int seq) {
        ActivityClientRecord r = mActivities.get(token);
        if (DEBUG_ORDER) Slog.d(TAG, "handlePauseActivity " + r + ", seq: " + seq);
        if (!checkAndUpdateLifecycleSeq(seq, r, "pauseActivity")) {
            return;
        }
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");

            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }
            mSomeActivitiesChanged = true;
        }
    }

handlePauseActivity主要做兩件事情

  • ActvityThread有一個(gè)mActivities集合跨跨,保存當(dāng)前App也就是launcher中所有打開的 Activity潮峦,把它找出來囱皿,然后讓它休眠
  • 通過AMP通知AMS,“我真的休眠了”

第四階段:AMS啟動(dòng)新的進(jìn)程
AMS要啟動(dòng)測試App,因?yàn)楹笈_(tái)進(jìn)程沒有該APP忱嘹,所以要啟動(dòng)一個(gè)新的進(jìn)程嘱腥,并且制定ActvityThread的main函數(shù)為入口函數(shù)。這階段了解即可

第五階段:新的進(jìn)程啟動(dòng)拘悦,以ActivityThread的main函數(shù)作為入口

public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();
        CloseGuard.setEnabled(false);
     //初始化應(yīng)用系統(tǒng)中的路徑
        Environment.initForCurrentUser();

        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());

        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);
        //設(shè)置進(jìn)程的名字
        Process.setArgV0("<pre-initialized>");
          //創(chuàng)建looper
        Looper.prepareMainLooper();
         
        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        // End of event ActivityThreadMain.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

thread.attach方法

    private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
          //代碼省略
        }
    }

實(shí)際調(diào)用的AMS中的attachApplication方法

 ActivityManagerService中的方法:
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

attachApplicationLocked代碼較長直接截取(這行需要注意下面還會(huì)分析第二個(gè)方法)

  AMS中的方法齿兔,主要功能有以下兩步
    private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
       //代碼省略
        主要用于創(chuàng)建Application,用調(diào)用onCreate方法
        thread.bindApplication(...);
        //代碼省略
        //主要用于創(chuàng)建Activity
        if (mStackSupervisor.attachApplicationLocked(app)) {
            //代碼省略
        }
    }

此時(shí)回到ActivityThread的bindApplication方法其實(shí)里面主要是這個(gè)方法

 sendMessage(H.BIND_APPLICATION, data);
//handlermessage中的方法
  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;

AppBindData會(huì)創(chuàng)建一個(gè)loadapk對(duì)象,標(biāo)記當(dāng)前APK信息
handleBindApplication源碼

private void handleBindApplication(AppBindData data) {
     try {
            //其他省略直接看這行,實(shí)際調(diào)用的LoadApk中的makeApplication方法
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;
    }
 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);
            appContext.setOuterContext(app);
        }
       if (instrumentation != null) {
            try {
                 //這行源碼就不看了實(shí)際就是調(diào)用onCreate方法
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
             //代碼省略
            }
        }
}
//newApplication最終走到這里,實(shí)際就是通過反射創(chuàng)建Application對(duì)象
  static public Application newApplication(Class<?> clazz, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }

回到剛才attachApplicationLocked中的源碼mStackSupervisor.attachApplicationLocked(app)源碼

    boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
       //代碼省略
        if (realStartActivityLocked(hr, app, true, true)) {
              //代碼省略
        }          
      //代碼省略
    }

    final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
           //代碼省略
        try {
            調(diào)用ApplicationThread的scheduleLaunchActivity用于啟動(dòng)一個(gè)Activity
            app.thread.scheduleLaunchActivity(...);
        } catch (RemoteException e) {
        }
    }

1)創(chuàng)建一個(gè)主線程Looper础米,也就是MainLooper分苇。注意,MainLooper就是在這里創(chuàng)建的屁桑。
2)創(chuàng)建Application医寿。注意,Application是在這里生成的蘑斧。
主線程在收到BIND_APPLICATION消息后靖秩,根據(jù)傳遞過來的ApplicationInfo創(chuàng)建一個(gè)loadApk對(duì)象(標(biāo)記當(dāng)前APK信息),然后創(chuàng)建ContextImpl對(duì)象(標(biāo)志當(dāng)前進(jìn)程的環(huán)境),緊接著通過反射創(chuàng)建目標(biāo)Application竖瘾,并調(diào)用其attach方法沟突,將ContextImpl對(duì)象設(shè)置為目標(biāo)Application的上下文環(huán)境,最后調(diào)用Application的onCreate函數(shù)捕传,做一些初始工作事扭。

第六階段:AMS告訴新APP啟動(dòng)哪個(gè)Activity
AMS把傳入ActivityThread對(duì)象轉(zhuǎn)換成ApplicationThread對(duì)象,用于以后和這個(gè)App跨進(jìn)程通信
在第一階段乐横,Launcher通知AMS,要啟動(dòng)測試APP的哪個(gè)Activity今野,在第二階段葡公,這個(gè)信息AMS保存下來,第六階段条霜,AMS從過去的記錄中翻出要啟動(dòng)哪個(gè)Activity,通過APT告訴app
第七階段:啟動(dòng)測試App的首頁Activity
回到剛才的第五階段接著分析app.thread.scheduleLaunchActivity(的源碼催什,實(shí)際是ActivityThread的scheduleLaunchActivity,里面實(shí)際就是發(fā)送了個(gè)消息

 sendMessage(H.LAUNCH_ACTIVITY, r);
 //handlerMessage中查看
 case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;

ActivityClientRecord 是AMS傳遞過來的要啟動(dòng)的Activity
getPackageInfoNoCheck方法宰睡,這個(gè)方法會(huì)提取apk中的所有資源蒲凶,然后設(shè)置r的packageInfo屬性。
handleLaunchActivity源碼分析

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
         //代碼省略
        Activity a = performLaunchActivity(r, customIntent);
      //代碼省略
    }
//performLaunchActivity源碼
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
           //通過反射獲得activity的實(shí)列
         Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
             //代碼省略
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            if (activity != null) {
                  //為activity創(chuàng)建一個(gè)上下文
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                  //將上下文傳給activity
                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, window);
                 //代碼省略
                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }
          //代碼省略
        return activity;
    }

1)通過Instrumentation的newActivity方法拆内,創(chuàng)建要啟動(dòng)的Activity實(shí)例旋圆。
2)為這個(gè)Activity創(chuàng)建一個(gè)上下文Context對(duì)象,并與Activity進(jìn)行關(guān)聯(lián)麸恍。
3)通過Instrumentation的callActivityOnCreate方法灵巧,執(zhí)行Activity的onCreate()方法搀矫,從而啟動(dòng)Activity。

參考書籍:<<android插件化開發(fā)指南>>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刻肄,一起剝皮案震驚了整個(gè)濱河市瓤球,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敏弃,老刑警劉巖卦羡,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異麦到,居然都是意外死亡绿饵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門隅要,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蝴罪,“玉大人,你說我怎么就攤上這事步清∫牛” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵廓啊,是天一觀的道長欢搜。 經(jīng)常有香客問我,道長谴轮,這世上最難降的妖魔是什么炒瘟? 我笑而不...
    開封第一講書人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮第步,結(jié)果婚禮上疮装,老公的妹妹穿的比我還像新娘。我一直安慰自己粘都,他們只是感情好廓推,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著翩隧,像睡著了一般樊展。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上堆生,一...
    開封第一講書人閱讀 49,741評(píng)論 1 289
  • 那天专缠,我揣著相機(jī)與錄音,去河邊找鬼淑仆。 笑死涝婉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔗怠。 我是一名探鬼主播嘁圈,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼省骂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了最住?” 一聲冷哼從身側(cè)響起钞澳,我...
    開封第一講書人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涨缚,沒想到半個(gè)月后轧粟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡脓魏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年兰吟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茂翔。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡混蔼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出珊燎,到底是詐尸還是另有隱情惭嚣,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布悔政,位于F島的核電站晚吞,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏谋国。R本人自食惡果不足惜槽地,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望芦瘾。 院中可真熱鬧捌蚊,春花似錦、人聲如沸近弟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽藐吮。三九已至,卻和暖如春逃贝,著一層夾襖步出監(jiān)牢的瞬間谣辞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來泰國打工沐扳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留泥从,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓沪摄,卻偏偏與公主長得像躯嫉,于是被迫代替她去往敵國和親纱烘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

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

  • Zygote是什么祈餐?有什么作用擂啥? Android系統(tǒng)底層基于Linux Kernel, 當(dāng)Kernel啟動(dòng)過程會(huì)創(chuàng)...
    Mr槑閱讀 2,804評(píng)論 4 18
  • 引言 Activity啟動(dòng)流程很多文章都已經(jīng)說過了,這里說一下自己的理解帆阳。Activity啟動(dòng)流程分兩種: 一種是...
    小彤花園閱讀 4,379評(píng)論 8 36
  • 好吧哺壶,終于要開始講解Activity的啟動(dòng)流程了,Activity的啟動(dòng)流程相對(duì)復(fù)雜一下蜒谤,涉及到了Activity...
    01_小小魚_01閱讀 889評(píng)論 1 1
  • Activity是Android應(yīng)用程序的四大組件之一,負(fù)責(zé)管理Android應(yīng)用程序的用戶界面山宾,一般一個(gè)應(yīng)用程序...
    泡面先生_Jack閱讀 11,200評(píng)論 7 40
  • 1.循環(huán) 1.1while 循環(huán) 當(dāng)你爬樓梯的時(shí)候 知道有 20 階臺(tái)階,所以有 >>> for step in ...
    Gentle_Kay閱讀 118評(píng)論 0 0