How does AndroidActivity start? How is the Activity lifecycle invoked?

In Android, there is an ActivityThread class, which can be regarded as the main thread class of the app. In Java, the entry for starting the app is the main() method. In Android, the main() method of ctivityThread is called when the app starts.

  public static void main(String[] args) {
        Trace.traceBegin(64L, "ActivityThreadMain");
        CloseGuard.setEnabled(false);
        Environment.initForCurrentUser();
        EventLogger.setReporter(new ActivityThread.EventLoggingReporter(null));
        File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);
        Process.setArgV0("<pre-initialized>");
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }

        Trace.traceEnd(64L);
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
Copy the code

Here are two key points:

  1. Looper.prepareMainLooper();

    Looper.loop();

    Start a Looper for message polling. Responsible for sending messages.
  2. An ActivityThread is created and the attach() method is called.
ActivityThread thread = new ActivityThread();
thread.attach(false);
Copy the code

attach()

private void attach(boolean system) { ... final IActivityManager mgr = ActivityManager.getService(); try { mgr.attachApplication(this.mAppThread); } catch (RemoteException var5) { throw var5.rethrowFromSystemServer(); }... }Copy the code

. Here we only look at the key code, through the ActivityManager getService (), generates a IActivityManager object, we see next

ActivityManager.getService()

 public static IActivityManager getService() {
        return (IActivityManager)IActivityManagerSingleton.get();
    }
    
    private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            IActivityManager am = Stub.asInterface(b);
            returnam; }};Copy the code

Here we see by ServiceManager. GetService () generates a Binder, and then by Binder interface communication. Finally, the generated ActivityManager is returned, which is managed by system service invocation and called through the Binder interface. Then look at attachApplication(this.mappthread) in attach(); The mAppThread: final ActivityThread. ApplicationThread mAppThread = new ActivityThread. ApplicationThread (null); Take a look at ApplicationThread, which is an inner class for ActivityThread.


    private class ApplicationThread extends android.app.IApplicationThread.Stub {
        ...
        }


public interface IApplicationThread extends IInterface {
    void schedulePauseActivity(IBinder var1, boolean var2, boolean var3, int var4, boolean var5) throws RemoteException;

    void scheduleStopActivity(IBinder var1, boolean var2, int var3) throws RemoteException;

    void scheduleWindowVisibility(IBinder var1, boolean var2) throws RemoteException;

    void scheduleResumeActivity(IBinder var1, int var2, boolean var3, Bundle var4) throws RemoteException;

    void scheduleSendResult(IBinder var1, List<ResultInfo> var2) throws RemoteException;

    void scheduleLaunchActivity(Intent var1, IBinder var2, int var3, ActivityInfo var4, Configuration var5, Configuration var6, CompatibilityInfo var7, String var8, IVoiceInteractor var9, int var10, Bundle var11, PersistableBundle var12, List<ResultInfo> var13, List<ReferrerIntent> var14, boolean var15, boolean var16, ProfilerInfo var17) throws RemoteException;

    void scheduleNewIntent(List<ReferrerIntent> var1, IBinder var2, boolean var3) throws RemoteException;

    void scheduleDestroyActivity(IBinder var1, boolean var2, int var3) throws RemoteException;

    void scheduleReceiver(Intent var1, ActivityInfo var2, CompatibilityInfo var3, int var4, String var5, Bundle var6, boolean var7, int var8, int var9) throws RemoteException;

    void scheduleCreateService(IBinder var1, ServiceInfo var2, CompatibilityInfo var3, int var4) throws RemoteException;

    void scheduleStopService(IBinder var1) throws RemoteException;

    void bindApplication(String var1, ApplicationInfo var2, List<ProviderInfo> var3, ComponentName var4, ProfilerInfo var5, Bundle var6, IInstrumentationWatcher var7, IUiAutomationConnection var8, int var9, boolean var10, boolean var11, boolean var12, boolean var13, Configuration var14, CompatibilityInfo var15, Map var16, Bundle var17, String var18) throws RemoteException;

    void scheduleExit() throws RemoteException;

    void scheduleConfigurationChanged(Configuration var1) throws RemoteException;

    void scheduleServiceArgs(IBinder var1, ParceledListSlice var2) throws RemoteException;

    void updateTimeZone() throws RemoteException;

    void processInBackground() throws RemoteException;

    void scheduleBindService(IBinder var1, Intent var2, boolean var3, int var4) throws RemoteException;

    void scheduleUnbindService(IBinder var1, Intent var2) throws RemoteException;

    void dumpService(ParcelFileDescriptor var1, IBinder var2, String[] var3) throws RemoteException;

    void scheduleRegisteredReceiver(IIntentReceiver var1, Intent var2, int var3, String var4, Bundle var5, boolean var6, boolean var7, int var8, int var9) throws RemoteException;

    void scheduleLowMemory() throws RemoteException;

    void scheduleActivityConfigurationChanged(IBinder var1, Configuration var2) throws RemoteException;

    void scheduleActivityMovedToDisplay(IBinder var1, int var2, Configuration var3) throws RemoteException;

    void scheduleRelaunchActivity(IBinder var1, List<ResultInfo> var2, List<ReferrerIntent> var3, int var4, boolean var5, Configuration var6, Configuration var7, boolean var8) throws RemoteException;

    void scheduleSleeping(IBinder var1, boolean var2) throws RemoteException;

    void profilerControl(boolean var1, ProfilerInfo var2, int var3) throws RemoteException;

    void setSchedulingGroup(int var1) throws RemoteException;

    void scheduleCreateBackupAgent(ApplicationInfo var1, CompatibilityInfo var2, int var3) throws RemoteException;

    void scheduleDestroyBackupAgent(ApplicationInfo var1, CompatibilityInfo var2) throws RemoteException;

    void scheduleOnNewActivityOptions(IBinder var1, Bundle var2) throws RemoteException;

    void scheduleSuicide() throws RemoteException;

    void dispatchPackageBroadcast(int var1, String[] var2) throws RemoteException;

    void scheduleCrash(String var1) throws RemoteException;

    void dumpHeap(boolean var1, boolean var2, boolean var3, String var4, ParcelFileDescriptor var5) throws RemoteException;

    void dumpActivity(ParcelFileDescriptor var1, IBinder var2, String var3, String[] var4) throws RemoteException;

    void clearDnsCache() throws RemoteException;

    void setHttpProxy(String var1, String var2, String var3, Uri var4) throws RemoteException;

    void setCoreSettings(Bundle var1) throws RemoteException;

    void updatePackageCompatibilityInfo(String var1, CompatibilityInfo var2) throws RemoteException;

    void scheduleTrimMemory(int var1) throws RemoteException;

    void dumpMemInfo(ParcelFileDescriptor var1, MemoryInfo var2, boolean var3, boolean var4, boolean var5, boolean var6, boolean var7, String[] var8) throws RemoteException;

    void dumpGfxInfo(ParcelFileDescriptor var1, String[] var2) throws RemoteException;

    void dumpProvider(ParcelFileDescriptor var1, IBinder var2, String[] var3) throws RemoteException;

    void dumpDbInfo(ParcelFileDescriptor var1, String[] var2) throws RemoteException;

    void unstableProviderDied(IBinder var1) throws RemoteException;

    void requestAssistContextExtras(IBinder var1, IBinder var2, int var3, int var4, int var5) throws RemoteException;

    void scheduleTranslucentConversionComplete(IBinder var1, boolean var2) throws RemoteException;

    void setProcessState(int var1) throws RemoteException;

    void scheduleInstallProvider(ProviderInfo var1) throws RemoteException;

    void updateTimePrefs(int var1) throws RemoteException;

    void scheduleEnterAnimationComplete(IBinder var1) throws RemoteException;

    void notifyCleartextNetwork(byte[] var1) throws RemoteException;

    void startBinderTracking() throws RemoteException;

    void stopBinderTrackingAndDump(ParcelFileDescriptor var1) throws RemoteException;

    void scheduleMultiWindowModeChanged(IBinder var1, boolean var2, Configuration var3) throws RemoteException;

    void schedulePictureInPictureModeChanged(IBinder var1, boolean var2, Configuration var3) throws RemoteException;

    void scheduleLocalVoiceInteractionStarted(IBinder var1, IVoiceInteractor var2) throws RemoteException;

    void handleTrustStorageUpdate() throws RemoteException;

    void attachAgent(String var1) throws RemoteException;

    void scheduleApplicationInfoChanged(ApplicationInfo var1) throws RemoteException;

    void setNetworkBlockSeq(long var1) throws RemoteException;


public abstract static class Stub extends Binder implements IApplicationThread {
Copy the code

As you can see, ApplicationThread inherits from iApplicationThread. Stub to implement classes that manage the activity lifecycle. AttachApplication is used by the ActivityThread to attach the applciationThread and store the activity information in the applciationThread. The apllicationThread class prepares the activity for various states.


When we open ApplicationThread, we see a bunch of schedle methods whose names tell us that they represent scheduled execution methods that are invoked when some state of the Activity is being executed

We see a scheduleLaunchActivity method that is called when the schedule is loaded

     public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ActivityInfo info, Configuration curConfig, Configuration overrideConfig, CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
            this.updateProcessState(procState, false);
            ActivityThread.ActivityClientRecord r = new ActivityThread.ActivityClientRecord();
            r.token = token;
            r.ident = ident;
            r.intent = intent;
            r.referrer = referrer;
            r.voiceInteractor = voiceInteractor;
            r.activityInfo = info;
            r.compatInfo = compatInfo;
            r.state = state;
            r.persistentState = persistentState;
            r.pendingResults = pendingResults;
            r.pendingIntents = pendingNewIntents;
            r.startsNotResumed = notResumed;
            r.isForward = isForward;
            r.profilerInfo = profilerInfo;
            r.overrideConfig = overrideConfig;
            this.updatePendingConfiguration(curConfig);
            ActivityThread.this.sendMessage(H.LAUNCH_ACTIVITY, r);
        }
        
        
    private class H extends Handler {
        public static final int LAUNCH_ACTIVITY = 100;

Copy the code

Finally we saw ActivityThread. This. SendMessage (100, r); LAUNCH_ACTIVITY sends a message through the handler and here we start the activity and we look at the handleLaunchActivity () method of handleMessage ()

 public void handleMessage(Message msg) {
            ActivityThread.ActivityClientRecord r;
            SomeArgs args;
            switch(msg.what) {
            case 100:
                Trace.traceBegin(64L, "activityStart");
                r = (ActivityThread.ActivityClientRecord)msg.obj;
                r.packageInfo = ActivityThread.this.getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);
                ActivityThread.this.handleLaunchActivity(r, (Intent)null, "LAUNCH_ACTIVITY");
                Trace.traceEnd(64L);
                break; . } } private void handleLaunchActivity(ActivityThread.ActivityClientRecord r, Intent customIntent, String reason) { this.unscheduleGcIdler(); this.mSomeActivitiesChanged =true;
        if(r.profilerInfo ! = null) { this.mProfiler.setProfiler(r.profilerInfo); this.mProfiler.startProfiling(); } this.handleConfigurationChanged((Configuration)null, (CompatibilityInfo)null);if(! ThreadedRenderer.sRendererDisabled) { GraphicsEnvironment.earlyInitEGL(); } WindowManagerGlobal.initialize(); Activity a = this.performLaunchActivity(r, customIntent);if(a ! = null) { r.createdConfig = new Configuration(this.mConfiguration); this.reportSizeConfigurations(r); Bundle oldState = r.state; this.handleResumeActivity(r.token,false, r.isForward, ! r.activity.mFinished && ! r.startsNotResumed, r.lastProcessedSeq, reason);if(! r.activity.mFinished && r.startsNotResumed) { this.performPauseActivityIfNeeded(r, reason);if(r.isPreHoneycomb()) { r.state = oldState; }}}else{ try { ActivityManager.getService().finishActivity(r.token, 0, (Intent)null, 0); } catch (RemoteException var6) { throw var6.rethrowFromSystemServer(); }}}Copy the code

The above we can see the Activity a = this. PerformLaunchActivity (r, customIntent);

private Activity performLaunchActivity(ActivityThread.ActivityClientRecord r, Intent customIntent) { ... Activity activity = null; try { ClassLoader cl = appContext.getClassLoader(); activity = this.mInstrumentation.newActivity(cl, component.getClassName(), r.intent); . } try { ... activity.mCalled =false;
                if (r.isPersistable()) {
                    this.mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    this.mInstrumentation.callActivityOnCreate(activity, r.state);
                }

                if(! activity.mCalled) { throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()");
                }

                r.activity = activity;
                r.stopped = true;
                if(! r.activity.mFinished) { activity.performStart(); r.stopped =false;
                }

                if(! r.activity.mFinished) {if (r.isPersistable()) {
                        if(r.state ! = null || r.persistentState ! = null) { this.mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState); }}else if (r.state != null) {
                        this.mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }

                if(! r.activity.mFinished) { activity.mCalled =false;
                    if (r.isPersistable()) {
                        this.mInstrumentation.callActivityOnPostCreate(activity, r.state, r.persistentState);
                    } else {
                        this.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;
    }

Copy the code

Here we have seen that different lifecycle methods are invoked for the activity depending on the situation.

Conclusion:

When an Application is running, the state of the Activity is actually changed through the Handler message mechanism.

In Application, the message mechanism is responsible for the call, because in the main method, our Looper is always training

When we load the Activity, we call a performLaunchActivity() method, and I find traces of our onCreate call in the middle.

Portal, thanks to BarryKerwin. Save for notes.