preface

First of all, a new daughter,

Var mDdaughter = new daughter ("6 years old ", "pretty and cute", "healthy and cute", "likes playing with little genius phone watch and her dad the most")Copy the code

One day, my daughter asked me,

“Dad dad, you say I play this little genius phone watch how so fierce, casually point at this small picture, the application came out, you can listen to children’s songs. It’s amazing.”

I was startled:

Little genius phone watch is running on Android, so this is not. Interviewers often test the application startup process! Is my daughter interviewing me?! 😭 well, since the daughter asked, that answer. But what do I say to this little zero-experience interviewer?

Answer the little interviewer

Daughter, you can imagine the watch inside a kindergarten, there is a teacher, a monitor, a class cadre, and a lot of children.

  • One teacher: Teacher Z (Zygote Process)

  • A monitor: Small A (ActivityManagerService)

  • A class leader: small L (Launcher desktop application)

  • Lots of kids: all apps, including music kids, chat kids, calendar kids, etc.

Application startup process is like a child wake up, after the boot, Z teacher will wake up the monitor and class cadres (SystemServer#ActivityManagerService, Launcher), small L wake up will go to understand the watch which children, what looks like (icon, Name), family information (package name, Androidmanifest), etc., and then one by one, paste the icon of your child’s photo on your own body. For example, there are music children, chat children, calendar children, in fact, is your watch on the table.

At this time, if you want to startA music kid, L will notify Her monitor, Binder. After A knows this, L will ask her to rest and go to teacher Z. Teacher Z is responsible for the music children to get up (fork process, start the ActivityThread), music children up and then find A to take her to wash her face and brush her teeth (start the ApplicationThread, Activity), all finished can perform A variety of performances, singing, dancing.

Don’t quite understand? Let’s have a chat and you’ll understand.

Daughter half understand not understand of gave me a praise 👍, dad you really great.

Fifteen years later

mDdaughter.grow(15)
mDdaughter.study("Android")
Copy the code

Fifteen years later, my daughter, now 21, is learning Android and wondering if she should follow her father’s lead.

One day, she came to me with a puzzled look on her face: “Dad, what is the process of launching this app? I have been watching it for a long time, but I still don’t understand it. Why don’t you tell me again in detail?” “Okay, don’t worry. I’ll tell you all about it this time.”

Answer for Android program ladies

Do you remember the story I told you when I was young? The Android system is like a kindergarten, with a friend called Launcher, and many other children’s business cards are posted on the body. The Launcher is our desktop. It uses the PackageManagerService to get information about all the applications in the system and display them. Of course, it is also an application.

By clicking on an application icon, the click event is triggered, and the startActivity method is executed. This overlaps with the start Activity step.

So what does this startActivity do? How did you wake up the app through all the hoops?

First of all, let’s introduce the key members of the system who played a key role in the app launch process.

Introduction to System members

  • The init processWhen Android starts, Zygote is not the first process, but the root Linux process init, which then starts Zygote.
  • The Zygote process, the parent of all Android processes, including SystemServer processes
  • SystemServer processAs its name shows, the system service process, which is responsible for all things large and small in the system, is also used to launch the three main managers (ActivityManagerService, PackageManagerService, WindowManagerService) and the binder thread pool.
  • ActivityManagerService, mainly responsible for the startup, switching, scheduling of the four major components of the system and the management and scheduling of application processes. The startup of some processes will be transmitted to AMS through Binder communication mechanism and then processed to Zygote.
  • PackageManagerService, mainly responsible for some operations of application package, such as installation, uninstall, parsing Androidmanifest.xml, scanning file information and so on.
  • WindowManagerService, mainly responsible for some window related services, such as window start, add, delete and so on.
  • LauncherDesktop applications have their own activities that start by default when they are started. They are implicitly started by setting intent.category_HOME Category.

Knowing these members, I followed me to see how to overcome all the difficulties and finally launched an App.

The first step: cross-process communication, tell the system my requirements

First of all, to tell the system, I the Launcher to start an application, call the Activity. The startActivityForResult method, will eventually turn to mInstrumentation. ExecStartActivity method. Since the Launcher itself is in a separate process, it needs to tell the system service across processes what I need to start my App. Find to inform the Service named ActivityTaskManagerService, then use AIDL, through a Binder to communicate with him.

Simple said here under ActivityTaskManagerService (ATMS). These communications, which were originally part of ActivityManagerService, are now distributed to THE ATMS, including scheduling for the four components. Also directly by the process of SystemServer startup, relevant source visible ActivityManagerService. Lifecycle. StartService method, interested friends can look at ourselves.

Moving on to cross-process communication, the code is as follows:

    //Instrumentation.java
    intresult = ActivityTaskManager.getService() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target ! =null ? target.mEmbeddedID : null,
                        requestCode, 0.null, options);


    //ActivityTaskManager.java            
    public static IActivityTaskManager getService(a) {
        return IActivityTaskManagerSingleton.get();
    }
    private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create(a) {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                    returnIActivityTaskManager.Stub.asInterface(b); }};//ActivityTaskManagerService.java
    public class ActivityTaskManagerService extends IActivityTaskManager.Stub
    
    public static final class Lifecycle extends SystemService {
        private final ActivityTaskManagerService mService;

        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityTaskManagerService(context);
        }

        @Override
        public void onStart(a) { publishBinderService(Context.ACTIVITY_TASK_SERVICE, mService); mService.start(); }}Copy the code

StartActivity is a very familiar method used to start an Activity. It is also used to start an application with an intent indicating which Activity to start.

Another point to note is that startActivity has a checkStartActivityResult method after it, which is used to check the result of starting the Activity. This method throws an exception when the Activity fails to start, such as a common problem: not registered in Androidmanifest.xml.

   public static void checkStartActivityResult(int res, Object intent) {
        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceofIntent && ((Intent)intent).getComponent() ! =null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            / /...}}Copy the code

Stage 2: Tell the Launcher to rest

When the ATMS receives the message to start, it will notify the previous application, that is, the Launcher, that it can rest and enter the Paused state.

    //ActivityStack.java

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
        / /...
        ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
        / /...
        boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false);
        if(mResumedActivity ! =null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, next, false);
        }
        / /...

        if (next.attachedToProcess()) {
            // The application has been started
            try {
                / /...
                transaction.setLifecycleStateRequest(
                        ResumeActivityItem.obtain(next.app.getReportedProcState(),
                                getDisplay().mDisplayContent.isNextTransitionForward()));
                mService.getLifecycleManager().scheduleTransaction(transaction);
                / /...
            } catch (Exception e) {
                / /...
                mStackSupervisor.startSpecificActivityLocked(next, true.false);
                return true;
            }
            / /...
            // From this point on, if something goes wrong there is no way
            // to recover the activity.
            try {
                next.completeResumeLocked();
            } catch (Exception e) {
                // If any exception gets thrown, toss away this
                // activity and try the next one.
                Slog.w(TAG, "Exception thrown during resume of " + next, e);
                requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null."resume-exception".true);
                return true; }}else {
            // Cold start process
            mStackSupervisor.startSpecificActivityLocked(next, true.true); }}Copy the code

There are two classes I haven’t seen:

  • ActivityStack, is the Activity of the stack management, equivalent to our usual project in the Activity management class, used to manage the state of the Activity, such as the order of the stack and so on.
  • ActivityRecordRepresents a specific Activity and stores various information about that Activity.

The startPausingLocked method is to put the previous application, in this case the Launcher, into Paused state. And then it’s going to determine if the app is started, and if it is, it’s going to go to the ResumeActivityItem method, and look at the name, and given that the app is started, have you guessed what it’s doing? Yes, this is used to control the Activity’s onResume lifecycle methods, not only is onResume onStart method, concrete ActivityThread handleResumeActivity method source code.

If not start would go on to startSpecificActivityLocked method, then look.

The third level: whether the process has been started, otherwise create the process

The Launcher after entering Paused, ActivityTaskManagerService will determine whether to open the application process has been started, if you have already started, then start the Activity can be directly, which is used in the start-up Activity process. If the process is not started, you need to create it.

There are two questions:

  • How do you tell if an application process exists? If an application is already started, one is saved in the ATMSWindowProcessControllerInformation, which includes processName and uid, which is the application ID and can be obtained from ApplicationInfo. uid. ProcessName is the processName, usually the package name. Therefore, to determine whether there is an application process, check whether there is a Corresponding WindowProcessController according to processName and UID, andWindowProcessControllerThe thread inside is not empty. The code is as follows:
    //ActivityStackSupervisor.java
    void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        final WindowProcessController wpc =
                mService.getProcessController(r.processName, r.info.applicationInfo.uid);

        boolean knownToBeDead = false;
        if(wpc ! =null && wpc.hasThread()) {
            // The application process exists
            try {
                realStartActivityLocked(r, wpc, andResume, checkConfig);
                return; }}}//WindowProcessController.java
    IApplicationThread getThread(a) {
        return mThread;
    }

    boolean hasThread(a) {
        returnmThread ! =null;
    }
Copy the code
  • Another question is how do you create a process? Remember Teacher Z? Yes, the Zygote process. It was stated earlier that it is the parent of all processes, so it needs to be notifiedZygoteFork a new process to serve the application.
    //ZygoteProcess.java
    private Process.ProcessStartResult attemptUsapSendArgsAndGetResult( ZygoteState zygoteState, String msgStr)
            throws ZygoteStartFailedEx, IOException {
        try (LocalSocket usapSessionSocket = zygoteState.getUsapSessionSocket()) {
            final BufferedWriter usapWriter =
                    new BufferedWriter(
                            new OutputStreamWriter(usapSessionSocket.getOutputStream()),
                            Zygote.SOCKET_BUFFER_SIZE);
            final DataInputStream usapReader =
                    new DataInputStream(usapSessionSocket.getInputStream());

            usapWriter.write(msgStr);
            usapWriter.flush();

            Process.ProcessStartResult result = new Process.ProcessStartResult();
            result.pid = usapReader.readInt();
            // USAPs can't be used to spawn processes that need wrappers.
            result.usingWrapper = false;

            if (result.pid >= 0) {
                return result;
            } else {
                throw new ZygoteStartFailedEx("USAP specialization failed"); }}}Copy the code

As you can see, the socket communicates with the Zygote, and the BufferedWriter reads and receives messages. The message that the new process will be created is passed to Zygote, who forks the process and returns the PID of the new process.

Might someone ask again? What is the fork? Why is there a socket for IPC communication instead of a Bindler?

  • First of all,fork()Is a method that is the primary method for creating processes on Unix-like operating systems. Used to create child processes (equivalent to a copy of the current process).
  • Why fork sockets instead of binders? Mainly because of forkMultithreading is not allowedBinder communication is multithreading, of all things.

The question is always coming up, and there are always curious friends asking, why can’t multiple threads be allowed in fork?

  • Prevent deadlocks. Actually, if you think about it, multi-threaded + multi-process, it doesn’t sound very good, does it? Let’s say that thread A in multiple threads is on some locklockAnother thread B calls the fork to create A child process, but the child process has no thread A, but the lock itself isforkOut, so no one can open the lock. Once another thread in the child processes the lock againlock, deadlocks.

Level 4: ActivityThread makes its debut

Zygote forks the process and returns the PID of the new process. The ActivityThread object is instantiated as well. Let’s see how this works:

   //RuntimeInit.java
   protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) { Class<? > cl;try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            m = cl.getMethod("main".new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }
        / /...
        return new MethodAndArgsCaller(m, argv);
    }
Copy the code

It was a reflection! The main method of ActivityThread is called through reflection. The ActivityThread, which you’re all familiar with, represents the main thread of Android, and the main method is the main entry to the app. This is not right! Call it when you create a new process, not the main entry. Take a look at the main entrance.

    public static void main(String[] args) {
        / /...
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        / /...

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

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

Copy the code

The main method basically creates the ActivityThread, creates the Looper object for the main thread, and starts the loop. In addition to this, tell AMS that I am awake and the process is created! Who is the attach of the code method, finally will turn to AMSattachApplicationLocked method, look at what this method do together:

    //ActivitymanagerService.java
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid, int callingUid, long startSeq) {
        / /...
        ProcessRecord app;
        / /...
        thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null.null.null, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || ! normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),
                        app.compat, getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial, autofillOptions, contentCaptureOptions);
        / /...
        app.makeActive(thread, mProcessStats);

        / /...
        // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true; }}/ /...
    }

    //ProcessRecord.java
    public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
        / /...
        thread = _thread;
        mWindowProcessController.setThread(thread);
    }
Copy the code

There are three main things done here:

  • BindApplication methodIs used to start the Application.
  • MakeActive methodSet the thread in WindowProcessController, which is used to determine whether the process exists.
  • AttachApplication method, starts the root Activity.

Create the Application

After an application is started, you should start Applicaiton and start Activity. To see what’s going on:

    //ActivityThread#ApplicationThread
    public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration config,
                CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial, AutofillOptions autofillOptions,
                ContentCaptureOptions contentCaptureOptions) {
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableBinderTracking = enableBinderTracking;
            data.trackAllocation = trackAllocation;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            data.buildSerial = buildSerial;
            data.autofillOptions = autofillOptions;
            data.contentCaptureOptions = contentCaptureOptions;
            sendMessage(H.BIND_APPLICATION, data);
        }

        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; }}Copy the code

You can see that there is an H, which is a Handler class for the main thread. H is used to handle all kinds of messages that the main thread needs to handle, including BIND_SERVICE, LOW_MEMORY, DUMP_HEAP, and so on. Next look at handleBindApplication:

    private void handleBindApplication(AppBindData data) {
        / /...
        try {
            final ClassLoader cl = instrContext.getClassLoader();
            mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        }
        / /...
        Application app;
        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
        try {
            // If the app is being launched for full backup or restore, bring it up in
            // a restricted environment with the base application class.
            app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;
            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if(! data.restrictedBackupMode) {if (!ArrayUtils.isEmpty(data.providers)) {
                    installContentProviders(app, data.providers);
                }
            }

            // 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);
            }
            / /...
            try {
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if(! mInstrumentation.onException(app, e)) {throw new RuntimeException(
                            "Unable to create application " + app.getClass().getName()
                                    + ":"+ e.toString(), e); }}}/ /...
    }
Copy the code

Here’s a little bit more information:

  • First, createInstrumentation“Is the first step in startActivity above. Each application has oneInstrumentationThis class is used to manage the process, such as when creating an Activity.
  • The makeApplication method, creates the Application, and we’re finally here. You’ll end up with the newApplication method, which executes the ApplicationattachMethods.
    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }
Copy the code

Now that attach method is available, when is onCreate called? Coming soon:

    instrumentation.callApplicationOnCreate(app);

    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }
Copy the code

Create Application->attach->onCreate call sequence.

Wait, there’s another important line of code before onCreate:

installContentProviders
Copy the code

Here is the relevant code to start the Provider, the specific logic will not be analyzed.

Level 6: Start the Activity

The bindApplication method is followed by the attachApplication method, and the handleLaunchActivity method is used for the active Thread.

    public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent) {
        / /...
        WindowManagerGlobal.initialize();
        / /...
        final Activity a = performLaunchActivity(r, customIntent);
        / /...
        return a;
    }
Copy the code

First, Windows ManagerGlobal is initialized. What is that? Yes, it is WindowManagerService, and it is also ready for subsequent window displays and so on.

Moving on to performLaunchActivity:

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        / / create ContextImpl
        ContextImpl appContext = createBaseContextForActivity(r);
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            / / create the Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
        }

        try {
            if(activity ! =null) {
                // Finish initializing some important data for the 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,
                        r.assistToken);

                if(customIntent ! =null) {
                    activity.mIntent = customIntent;
                }

                // Set the activity's theme
                int theme = r.activityInfo.getThemeResource();
                if(theme ! =0) {
                    activity.setTheme(theme);
                }

                // Call the activity's onCreate method
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else{ mInstrumentation.callActivityOnCreate(activity, r.state); }}}return activity;
    }
Copy the code

Wow, finally see the onCreate method. Hold on, let’s take a look at this code step by step.

So first of all, I’m creating a ContextImpl object, ContextImpl for those of you who don’t know what it is, ContextImpl inherits from Context, which is actually the Context that we use. Some of you might say, well, that’s not right, getting the Context is getting the Context object. Let’s follow the source code.

    //Activity.java
    Context mBase;

    @Override
    public Executor getMainExecutor(a) {
        return mBase.getMainExecutor();
    }

    @Override
    public Context getApplicationContext(a) {
        return mBase.getApplicationContext();
    }
Copy the code

MBase = mBase; mBase = mBase;

    protected void attachBaseContext(Context base) {
        if(mBase ! =null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

    // Layer by layer

    final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
        
        attachBaseContext(context);

        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }

       
    }

Copy the code

That’s the attach from the launch Activity method. So this ContextImpl is the context we normally use.

By the way, what else did Attach do? Create a PhoneWindow, associate itself with the Window, and set setSoftInputMode, etc.

After ContextImpl is created, the class loader creates the Activity object, sets the Activity theme, and calls the Activity’s onCreate method.

conclusion

Let’s go through the App startup process again:

  • LauncherThe called click event goes to the startActivity method of the Instrumentation class.
  • InstrumentationAMS is told the requirements to start the application through cross-process communication.
  • AMSFeed back the Launcher and put the Launcher into Paused state
  • LauncherOnce in Paused state, AMS goes to the ZygoteProcess class and communicates with Zygote over the socket to inform Zygote that it needs to create a new process.
  • ZygoteFork the process and call the Main method of ActivityThread, which is the entry point to the app.
  • ActivityThreadThe main method creates a new ActivityThread instance and a new Looper instance to start the loop.
  • At the same timeActivityThreadAMS is also told that the process has been created. Start creating the Application Provider and call the Attach, onCreate method of Applicaiton.
  • The last step is to create a context that loads the Activity through the class loader and calls the ActivityonCreateMethods.

At this point, the application is started.

Of course, the purpose of analyzing source code has always been not to learn knowledge and learn, but to understand these foundations, we can better solve the problem. After learning the startup process of App, we can think about some problems we didn’t understand thoroughly before, such as startup optimization.

Analyzing the startup process, there are actually three areas that can optimize the startup speed:

  • Attach method of ApplicationThe MultiDex application will execute the MultiDex logic inside the method. Therefore, MultiDex optimization can be carried out here. For example, Toutiao solution is to start a separate process of activity to load MultiDex.
  • Application's onCreate methodA lot of the initialization of tripartite libraries takes place here, so we can turn on thread pooling, lazy loading, etc. Make a distinction between each startup task, which can be run by sub-threads, and which can be run in sequence.
  • The onCreate method of the Activity, also for thread processing, lazy loading. Or pre-create activities, pre-load classes, and so on.

Finally, I hope you can have a cute and lovely daughter/son. 😊

The attachment

Fork optimized app startup process analysis using multi-threading Toutiao Launch


My public number: code on building blocks, every day three interview questions, detailed analysis, help you become offer harvester.

Thank you for reading, and if you think it’s ok, just give it a thumbs up! Thank you! One of your 👍 is my motivation to share ❤️.