Application的創(chuàng)建、Activity的創(chuàng)建

關(guān)于Activity需要知道的更多內(nèi)容

前言

Activity作為作為四大組件中我們最常見的一個(gè)組件,經(jīng)常接觸使用,但是往往每次讓我們對(duì)這個(gè)組件進(jìn)行說明的時(shí)候,我們只知道它的幾個(gè)生命周期,幾種啟動(dòng)模式,但是具體的更多的就講不出來了。
ps:我在寫這個(gè)之前實(shí)際上也是一知半解,所以今天我們一起去看看Activity更多的東西,源碼版本為 android-26

  • 1、Application的創(chuàng)建
  • 2、Activity的創(chuàng)建和生命周期

一、Application的創(chuàng)建

我們知道,java程序想運(yùn)行都是通過調(diào)用main方法來啟動(dòng),我們的Android應(yīng)用程序也是如此,但是我們每次都是直接點(diǎn)擊手機(jī)屏幕的應(yīng)用圖標(biāo)就直接啟動(dòng)了app,這時(shí)候難免有疑惑,我們?yōu)槭裁床恍枰{(diào)用main方法就可以直接啟動(dòng)我們的程序呢,雖然我們沒有直接的去寫main方法,但是實(shí)際上還是通過ActivityThread類的main方法來作為我們應(yīng)用程序的入口。

# ActivityThread類
public static void main(String[] args) {
        ...
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();//1、這邊new了一個(gè)ActivityThread對(duì)象
        thread.attach(false);//2、這邊去進(jìn)行連接,連接什么?
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

在ActivityThread類中,能看到一個(gè)main方法,它就是我們程序的入口,在注釋1的地方,會(huì)去創(chuàng)建一個(gè)ActivityThread對(duì)象,在注釋2的地方,調(diào)用thread的attach方法去連接,具體的連接什么我們繼續(xù)看下面的代碼

  #ActivityThread類
  private void attach(boolean system) {
        ...
        if (!system) {
            ...
            final IActivityManager mgr = ActivityManager.getService();//1、通過AIDL,獲取AMS的代理對(duì)象IActivityManager
            try {
                mgr.attachApplication(mAppThread);//2、這邊將AMS和我們的應(yīng)用進(jìn)程application進(jìn)行連接
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        } else {
            ...
        }
    }

關(guān)于AIDL,這邊不進(jìn)行展開,我們關(guān)心的是注釋2,這邊通過AIDL將AMS和我們應(yīng)用進(jìn)程application進(jìn)行連接,具體的是調(diào)用ActivityManagerService的attachApplication方法進(jìn)行連接。

  #ActivityManagerService類
  @Override
  public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();//1、獲取pid
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);//2、傳入pid進(jìn)行連接
            Binder.restoreCallingIdentity(origId);
        }
    }

這邊的注釋1通過Binder對(duì)象獲取應(yīng)用的pid,注釋2處調(diào)用attachApplicationLocked的方法傳入pid連接application。需要注意的這邊加了synchronized關(guān)鍵字,表示我們需要等待這里執(zhí)行完畢才能下一步,也就是說我們一個(gè)應(yīng)用需要當(dāng)我們application被連接后才能走下面的流程。

##ActivityManagerService
private final boolean attachApplicationLocked(IApplicationThread thread,
                                                  int pid, int callingUid, long startSeq) {
        ProcessRecord app;  //1、進(jìn)程記錄類,保存相關(guān)的信息
        long startTime = SystemClock.uptimeMillis();
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);  //2、根據(jù)id獲取相關(guān)信息賦值給記錄對(duì)象
            }
        } 
        ...
        if (app.instr != null) {  //3、判斷進(jìn)程是否正在活躍
           //Application 4、綁定到當(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);   
        } else {
            //Application 4、綁定到當(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);  
        }
        ...
        // See if the top visible activity is waiting to run in this process...
        //查看頂部可見活動(dòng)是否正在等待在此進(jìn)程中進(jìn)行
        if (normalMode) {
            try {
                //TODO 5、Activity創(chuàng)建的分析
                //檢測top的Activity是否在運(yùn)行中等待
                if (mStackSupervisor.attachApattachApplicationplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }

        // Find any services that should be running in this process...
        //查看在此進(jìn)程中進(jìn)行的服務(wù)
        if (!badApp) {
            try {
                didSomething |= mServices.attachApplicationLocked(app, processName);
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }

        // Check if a next-broadcast receiver is in this process...
        //查看在此進(jìn)程中進(jìn)行的廣播接收者
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
            try {
                didSomething |= sendPendingBroadcastsLocked(app);
                checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
            } catch (Exception e) {
                // If the app died trying to launch the receiver we declare it 'bad'
                Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
                badApp = true;
            }
        }

        // Check whether the next backup agent is in this process...
        //檢測下一個(gè)備份代理是否在此進(jìn)程中
        if (!badApp && mBackupTarget != null && mBackupTarget.app == app) {
            if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
                    "New app is backup target, launching agent for " + app);
            notifyPackageUse(mBackupTarget.appInfo.packageName,
                    PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
            try {
                thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
                        compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
                        mBackupTarget.backupMode);
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
                badApp = true;
            }
        }
        ...
}

看具體的attachApplicationLocked方法里面,注釋1處創(chuàng)建了一個(gè)進(jìn)程記錄對(duì)象用來保存進(jìn)程的相關(guān)信息,注釋2根據(jù)id獲取到相關(guān)信息賦值給記錄對(duì)象,注釋3先判斷進(jìn)行是否活躍,然后調(diào)用bindApplication的方法進(jìn)行application的綁定,這邊的thread是IApplicationThread對(duì)象,IApplicationThread它是一個(gè)AIDL的接口,是系統(tǒng)進(jìn)程調(diào)用應(yīng)用進(jìn)程的接口,它的實(shí)現(xiàn)類是ApplicationThread,是一個(gè)在ActivityThread的內(nèi)部類,注釋5的地方是關(guān)于Activity的創(chuàng)建,我們這邊先跳過,等我們將Application進(jìn)行綁定完成后在來分析。

##ActivityThread.ApplicationThread
public final void bindApplication(String processName, ApplicationInfo appInfo...,String buildSerial) {

            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            setCoreSettings(coreSettings);//1、添加核心設(shè)置

            //2、將bindApplication帶進(jìn)來的信息封裝到AppBindData類中,通過handler發(fā)送出去
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            ...
            sendMessage(H.BIND_APPLICATION, data);//3、將data通過handler發(fā)送出去,具體的WHAT 是 H.BIND_APPLICATION
        }

在注釋1會(huì)去添加一些核心的設(shè)置,我們這邊就不去關(guān)注,我們看注釋2的地方,去將帶進(jìn)來的信息封裝到data中然后在注釋3通過handler發(fā)送出去,具體的WHAT 是 H.BIND_APPLICATION。H是一個(gè)繼承Handler的子類,這邊我們?nèi)タ聪孪⑹侨绾伪环职l(fā)處理的。

##ActivityThread.H
public void handleMessage(Message msg) {
            ...
        switch (msg.what) {
            ...
           case BIND_APPLICATION:
                    //1、這邊進(jìn)行handler消息的處理 處理創(chuàng)建Application的消息
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                    AppBindData data = (AppBindData) msg.obj;
                    handleBindApplication(data);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
            ...
        }
        ...
}

這邊注釋1處理創(chuàng)建Application的消息,調(diào)用handleBindApplication的方法去綁定application

  ##ActivityThread
  private void handleBindApplication(AppBindData data) {

        final InstrumentationInfo ii;//1、創(chuàng)建InstrumentationInfo對(duì)象

        ...

       
        final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); 2、 //獲取application的context上下文
        
        //  3、加載instrumentation
        if (ii != null) {
            ...
            
            mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection); //4、instrumentation初始化
            ...
        } else {
            mInstrumentation = new Instrumentation();
        }

        try {
          
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);//5、通過makeApplication方法創(chuàng)建application

            ...
            
            // Do this after providers, since instrumentation tests generally start their
            // test thread at this point, and we don't want that racing.
            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            } catch (Exception e) {
                throw new RuntimeException(
                        "Exception thrown in onCreate() of "
                                + data.instrumentationName + ": " + e.toString(), e);
            }

            try {
                mInstrumentation.callApplicationOnCreate(app);//6、回調(diào)application的onCreate方法
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                            "Unable to create application " + app.getClass().getName()
                                    + ": " + e.toString(), e);
                }
            }
        } finally {
            StrictMode.setThreadPolicy(savedPolicy);
        }
    }

這個(gè)方法里面處理了許多事情,注釋1創(chuàng)建了一個(gè)InstrumentationInfo對(duì)象,在注釋2獲取了application的上下文,注釋3和4去加載并初始化了InstrumentationInfo,注釋5是我們的關(guān)鍵地方,通過調(diào)用makeApplication的方法創(chuàng)建了我們的application,我們看下makeApplication的方法都做了什么操作。然后在注釋6調(diào)用InstrumentationInfo去回調(diào)application的onCreate方法,到這里我們的application就創(chuàng)建并且回到了我們熟悉onCreate方法。

 ##LoadedApk
 public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
        if (mApplication != null) {//1、如果mApplication不為null,直接返回mApplication對(duì)象
            return mApplication;
        }
      
        Application app = null;
       //如果是有自定義的application,就用這個(gè),如果沒有,就用系統(tǒng)的application
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }
        try {
            //2、獲得類加載器然后通過反射去new一個(gè)Appliction
            java.lang.ClassLoader cl = getClassLoader();
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            ...
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;//3、賦值給mApplication

        if (instrumentation != null) {//4、這邊會(huì)為instrumentation是為null的
            try {
                instrumentation.callApplicationOnCreate(app);//5、這邊如果instrumentation不為null,才能執(zhí)行到這里
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                   ...
                }
            }
        }
        ...
        return app;
    }

這邊我們首先判斷mApplication如果不為null,直接返回這個(gè)對(duì)象,如果為null的話,我們通過類加載然后反射去new出一個(gè)application對(duì)象并且賦值給mApplication,還有這邊因?yàn)槲覀冊(cè)谡{(diào)用makeApplication方法時(shí)傳入的Instrumentation是個(gè)null對(duì)象,所以我們這邊不會(huì)去執(zhí)行
callApplicationOnCreate回調(diào)onCreate方法的。具體的回調(diào)onCreate會(huì)在上面的源碼注釋6的地方去執(zhí)行回調(diào)。

二、Activity的創(chuàng)建

這邊我們首先需要知道Activity的狀態(tài)和生命周期

狀態(tài):運(yùn)行、暫停、停止、銷毀(運(yùn)行和暫停是不可見的,停止和銷毀是不可見的)
生命周期:包括了常見的onCreate、onResume、onStart、onPause、onStop、onDestory等

上面的分析過程中我們?cè)贏ctivityManagerService類中留了一個(gè)

##ActivityManagerService
private final boolean attachApplicationLocked(IApplicationThread thread,
                                                  int pid, int callingUid, long startSeq) {
        ...
 //5、檢測最可見的Activity是否在運(yùn)行進(jìn)程中等待,如果再則創(chuàng)建Activity
        //TODO 待分析Activity的創(chuàng)建
        if (mStackSupervisor.attachApplicationLocked(app)) {  
            didSomething = true;
        }
}
...

這邊我們對(duì)它進(jìn)行深入下看看是如何創(chuàng)建的

 ##ActivityStackSupervisor
 boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        ...
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (!isFocusedStack(stack)) {
                    continue;
                }
                //ActivityRecord來維護(hù)Activity運(yùn)行時(shí)的狀態(tài)信息,需要將Activity綁定到AMS,ActivityRecord才能開始Activity的生命周期
                ActivityRecord hr = stack.topRunningActivityLocked();
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                            if (realStartActivityLocked(hr, app, true, true)) {//1、真正的創(chuàng)建Activity
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            throw e;
                        }
                    }
                }
            }
        }
        ...
        return didSomething;
    }

在realStartActivityLocked我們會(huì)創(chuàng)建Activity

##ActivityStackSupervisor
 final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
        ...

        r.startFreezingScreenLocked(app, 0);//1、開始屏幕相關(guān)的啟動(dòng)
        

        // schedule launch ticks to collect information about slow apps.
        r.startLaunchTickingLocked();//2、啟動(dòng)定時(shí)鎖定

        r.app = app;
        app.waitingToKill = null;
        r.launchCount++;//3、每啟動(dòng)一次launchCount的數(shù)量自增
        r.lastLaunchTime = SystemClock.uptimeMillis();//4、修改最后一次的啟動(dòng)時(shí)間

        final ActivityStack stack = task.getStack();
        try {
            ...

            //5、根據(jù)具體的包名,通知應(yīng)用

         mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
                                      PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
            
            ...

            //6、調(diào)用ApplicationThread的scheduleLaunchActivity 方法去啟動(dòng)LaunchActivity
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    // TODO: Have this take the merged configuration instead of separate global and
                    // override configs.
                    mergedConfiguration.getGlobalConfiguration(),
                    mergedConfiguration.getOverrideConfiguration(), r.compat,
                    r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                    r.persistentState, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profilerInfo);

            ...
        } catch (RemoteException e) {
            ...
        }

        ...
        if (isFocusedStack(stack)) {
            mService.startSetupActivityLocked();7、開始設(shè)置活動(dòng)鎖
        }
        if (r.app != null) {
            mService.mServices.updateServiceConnectionActivitiesLocked(r.app);//8、更新服務(wù)連接活動(dòng)鎖
        }

        return true;
    }

這邊的注釋很多,但是我們主要關(guān)心的是注釋6,這邊調(diào)用ApplicationThread的scheduleLaunchActivity 方法去啟動(dòng)LaunchActivity,我們回到ApplicationThread

##ActivityThread.ApplicationThread
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                                       ..., ProfilerInfo profilerInfo) {

    updateProcessState(procState, false);

    ActivityClientRecord r = new ActivityClientRecord();
    ...

    sendMessage(H.LAUNCH_ACTIVITY, r);//通過handler發(fā)送啟動(dòng)Activity的消息
}

這邊是不是很眼熟,我們剛剛的application的綁定也是通過handler去發(fā)送消息去處理(這邊我們能發(fā)現(xiàn)handler是有多么重要了吧,哈哈),我們?nèi)ctivityThread的子類H去看下具體的activity創(chuàng)建的消息處理

public void handleMessage(Message msg) {
        switch (msg.what) {
            case LAUNCH_ACTIVITY: {//1、接收到關(guān)于創(chuàng)建Activity的消息,進(jìn)行處理
                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");//2、去創(chuàng)建LaunchActivity
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
}

根據(jù)message的what值我們找到了具體的消息處理,這邊會(huì)通過handleLaunchActivity去處理我們Activity創(chuàng)建

##ActivityThread
 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        ...
        Activity a = performLaunchActivity(r, customIntent);//1、去執(zhí)行LaunchActivity

        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);//2、處理可見Activity
            ...
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
            //3、這邊如何activity是個(gè)null的對(duì)象,直接通過ActivityManagerService調(diào)用finishActivity去關(guān)閉掉
                ActivityManager.getService()
                        .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

這邊我們先看注釋1的performLaunchActivity方法

##ActivityThread
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        ...

        ActivityInfo aInfo = r.activityInfo;//1、獲取Activity的信息
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }
        ...

        ContextImpl appContext = createBaseContextForActivity(r);//2、獲取Acitivty的上下文
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();//3、獲取類加載器,使用cl(類加載器)加載出Activity,再使用反射new出Activity
            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 {
            //4、這邊又去調(diào)用一次makeApplication方法
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            if (activity != null) {
                ...
                appContext.setOuterContext(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, r.configCallback);

                ...
                if (r.isPersistable()) {//5、這邊去調(diào)用Activity的onCreate方法
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                ...

        } catch (SuperNotCalledException e) {
            throw e;

        } catch (Exception e) {
           ...
        }
        return activity;
    }

在注釋3我們會(huì)發(fā)現(xiàn)這邊是獲取類加載去然后通過反射去new出一個(gè)Activity,然后在注釋5去回調(diào)Activity的onCreate方法,到這邊我們就能去調(diào)用我們的setContentView去加載布局了。注釋4的地方又調(diào)用了一次makeApplication方法,如果Application不為null,直接返回application對(duì)象。
現(xiàn)在我們回到上一個(gè)源碼的注釋2那里,看看handleResumeActivity都做了什么?

##ActivityThread
 final void handleResumeActivity(IBinder token,
                                    boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ...
        r = performResumeActivity(token, clearHide, reason);
        ...
    }

這個(gè)方法里面有很多代碼,我們只需要去看performResumeActivity方法

##ActivityThread
public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide, String reason) {
    ...
    r.activity.performResume();//主要是這個(gè)方法
    ...
    return r;
}

這邊是調(diào)用Activity的performResume方法

##Activity
final void performResume() {
        performRestart();

        mFragments.execPendingActions();

        mLastNonConfigurationInstances = null;

        mCalled = false;
        // mResumed is set by the instrumentation
        mInstrumentation.callActivityOnResume(this);//回調(diào)Activity的onResume方法
       
    }

到這邊我們就能發(fā)現(xiàn)它跟Activity的onCreate的回調(diào)是類似的,都是通過mInstrumentation.callActivityxxx去回調(diào)執(zhí)行。

沿著別人走過的路,跟上去發(fā)現(xiàn)不一樣的風(fēng)景

參考鏈接:http://www.itdecent.cn/p/f55467033146

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

友情鏈接更多精彩內(nèi)容