美文网首页
深入浅出 App 启动过程

深入浅出 App 启动过程

作者: 简简单单敲代码 | 来源:发表于2018-03-02 18:09 被阅读56次

Android 有四大组件,我们用的最多的就是 activity。在开发中我们有过无数次startActivity那么在这个过程中究竟会是一个怎么样的调用过程,这个博客会详细介绍 Activity启动过程。

App 启动过程

作为一个 android 开发者,一定是有一定的 Java 基础,下面这段代码肯定是最熟悉不过的。

public class Test1 {

    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

大家都知道,Java 中的入口是 main方法,android 也是用 Java 编写的,那么一个应用的入口是不是 main 方法?

翻阅源码,你会发现在 android 源码中有一个核心类ActivityThread中就有这个神奇的main方法。

public final class ActivityThread {
    //...
   private class ApplicationThread extends ApplicationThreadNative {
    //...
    }
    //...
    private class H extends Handler {
    //...
    }
    //...
   public static void main(String[] args) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
        SamplingProfilerIntegration.start();

        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);

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

        Process.setArgV0("<pre-initialized>");

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

其中先是进行一些初始化,然后Looper.prepareMainLooper()方法初始化了 Looper对面。

    /**
     * Initialize the current thread as a looper, marking it as an
     * application's main looper. The main looper for your application
     * is created by the Android environment, so you should never need
     * to call this function yourself.  See also: {@link #prepare()}
     */
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }

然后再初始化了ActivityThread对象并且调用了attach方法。

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

这个方法在这里是一个比较关键的方法,需要详细的读一下:

private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
           //对view进行初始化操作而进行添加的一个处理的handler对象,
           //有人对ViewRootImpl的理解是一个handler对象来处理view相关的方法
            ViewRootImpl.addFirstDrawHandler(new Runnable() {
                @Override
                public void run() {
           //JIT Just In Time Compiler
                    ensureJitEnabled();
                }
            });
            android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                    UserHandle.myUserId());
          //调用 RuntimeInit.setApplicationObject() 方法,
          //把对象mAppThread(Binder)放到了RuntimeInit类中的静态变量mApplicationObject中。 
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            //获得AMS(ActivityManagerService)实例, AMS的log tag: "ActivityManager"
           final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
           //把ApplicationThread对象传给AMS
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
          //....
           }
          //....
    }

不是系统级别的 APP,所以我们直接看!system里面执行的代码。主要看做的两件事情。

  • ApplicationThread
    把对象mAppThread(Binder)放到了RuntimeInit类中的静态变量mApplicationObject中。mAppThread的类型是ApplicationThread,它是ActivityThread的成员变量,定义和初始化如下:
final ApplicationThread mAppThread = new ApplicationThread();
  • ActivityManagerService(AMS)
public final class ActivityManagerService extends ActivityManagerNative {
        //...
    public final void attachApplication(IApplicationThread thread) {
        // ...
        attachApplicationLocked(thread, callingPid);
        //...
    }
    ...
    private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
        //....
        //通过binder,跨进程调用ApplicationThread的bindApplication()方法, 
        //以下代码调回ActivityThread.java#ApplicationThread
            thread.bindApplication(processName, appInfo, providers,
                    app.instrumentationClass, profileFile, profileFd, profileAutoStop,
                    app.instrumentationArguments, app.instrumentationWatcher,
                    app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                    mCoreSettingsObserver.getCoreSettingsLocked());
        //....

    }
}

我们接着继续看回调过来 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<String, IBinder> services, Bundle coreSettings) {

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

            setCoreSettings(coreSettings);

            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;
            sendMessage(H.BIND_APPLICATION, data);
        }
//...

在这里封装了一些需要然后最后调用了sendMessage的方法,我们继续来追一下这个方法:

 private void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1) {
        sendMessage(what, obj, arg1, 0, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2) {
        sendMessage(what, obj, arg1, arg2, false);
    }

    private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

我们可以清楚的看到最调用了 mH.sendMessage(msg);这个方法,我们再看一下这个mH是何方神圣?它是ActivityThread 的成员变量来自于一个H的对象。

 final H mH = new H();

那么这个 H 又是什么?

  private class H extends Handler {
    //...
  public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                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;
                case RELAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                    handleRelaunchActivity(r);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                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;
                case PAUSE_ACTIVITY_FINISHING: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handlePauseActivity((IBinder) args.arg1, true, (args.argi1 & USER_LEAVING) != 0,
                            args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case STOP_ACTIVITY_SHOW: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleStopActivity((IBinder) args.arg1, true, args.argi2, args.argi3);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case STOP_ACTIVITY_HIDE: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleStopActivity((IBinder) args.arg1, false, args.argi2, args.argi3);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case SHOW_WINDOW:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
                    handleWindowVisibility((IBinder)msg.obj, true);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                case HIDE_WINDOW:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
                    handleWindowVisibility((IBinder)msg.obj, false);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                case RESUME_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
                    SomeArgs args = (SomeArgs) msg.obj;
                    handleResumeActivity((IBinder) args.arg1, true, args.argi1 != 0, true,
                            args.argi3, "RESUME_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                case SEND_RESULT:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
                    handleSendResult((ResultData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                case DESTROY_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
                    handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
                            msg.arg2, false);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                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;
                case EXIT_APPLICATION:
                    if (mInitialApplication != null) {
                        mInitialApplication.onTerminate();
                    }
                    Looper.myLooper().quit();
                    break;
                case NEW_INTENT:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
                    handleNewIntent((NewIntentData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
          //太多了,随便删了点,大家可以自行查阅源码
            }
            Object obj = msg.obj;
            if (obj instanceof SomeArgs) {
                ((SomeArgs) obj).recycle();
            }
            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
        }
    //...
  }

再次提取一下这个 case

 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立即调用了handleBindApplication(data);方法,看名字大致就知道什么意思了,不过我们还是来追一下代码。

private void handleBindApplication(AppBindData data) {
       //....
      //appContext
           final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
      
        // Continue loading instrumentation.
        if (ii != null) {
            final ApplicationInfo instrApp = new ApplicationInfo();
            ii.copyTo(instrApp);
            instrApp.initForUser(UserHandle.myUserId());
            final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true, false);
            final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

        //创建Instrumentation 对象      
                final ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            final ComponentName component = new ComponentName(ii.packageName, ii.name);
            mInstrumentation.init(this, instrContext, appContext, component,
                    data.instrumentationWatcher, data.instrumentationUiAutomationConnection);  
       //在这里创建了Applicaiton类的对象
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;
        //如果有ContentProvider的话, 先加载ContentProvider,后调用Application的onCreate()方法
        List<ProviderInfo> providers = data.providers;
        if (providers != null) {
            installContentProviders(app, providers);
        }
        //通过mInstrumentation 最终会回调Application OnCreate方法
            mInstrumentation.callApplicationOnCreate(app);
          

那就继续追一下Instrumentation中是怎么样回调到 Application OnCreate()方法

//...
public class Instrumentation {
//...
    public void callApplicationOnCreate(Application app) {
        app.onCreate();
    }
//...
}

至此,APP 已经启动了,并且回调了Application.onCreate();方法。App 启动过程浅出至此。

相关文章

  • 深入浅出 App 启动过程

    Android 有四大组件,我们用的最多的就是 activity。在开发中我们有过无数次startActivity...

  • android开发艺术探索第九章心得(四大组件的工作过程)

    app的启动过程 app的启动过程其实是在AMS和ActivityThread(ApplicationThread...

  • 深入理解iOS App的启动过程

    前言 参考资料:深入理解iOS App的启动过程iOS 应用程序启动过程及原理总结iOS:App启动过程详解(不同...

  • iOS 启动过程分析及优化

    APP启动过程分析 本文主要通过我们对于APP启动过程的分析,然后去剖析如何去进行启动时间的优化,以达到APP性能...

  • 启动时间优化

    1、APP启动 1.1、APP启动为什么这么重要 App 启动是和用户的第一个交互过程,所以要尽量缩短这个过程的时...

  • App启动流程:总体说明

    概述: “应用程序启动过程”其实说的就是“冷启动”过程。 App启动流程总体是由以下3部分组成 为目标App启动做...

  • APP启动过程简单分析

    APP启动过程 上图就可以很好的说明App启动的过程 ActivityManagerService组织回退栈时以A...

  • app冷启动优化方案

    App启动过程 app启动分为冷启动和热启动,热启动是App刚结束后再启动,有部分在内存但没有进程存在。我们所做的...

  • iOS底层探索30、启动优化分析

    引言 APP 启动,对用户而言,是从点击 APP 开始,到看到 APP 首页展现的过程。 冷启动:针对APP,内存...

  • App启动时间监测以及优化

    App启动类型 热启动,App启动后退到后台,App目前还是在系统的进程中,此时App重新进入前台这个过程就是热启...

网友评论

      本文标题:深入浅出 App 启动过程

      本文链接:https://www.haomeiwen.com/subject/yrwaxftx.html