详解安卓从图表icon点击到APP启动界面加载流程

首先要明确一点:在Android系统中,应用程序是由Launcher启动起来的,其实,Launcher本身也是一个应用程序,其它的应用程序安装后,就会Launcher的界面上出现一个相应的图标,

点击这个图标时,Launcher就会对应的应用程序启动起来。

1.用户在手机桌面点击要启动的软件的icon,此时我们的上下文是Launcher的进程,对于Launcher.java,继承了Activity,在其点击事件中,调用了

startActivitySafely(intent, tag);

   startActivity(intent);

           startActivityForResult(intent, -1);  显然这里会通过ActivityManagerService的远程接口,即ActivityManagerProxy接口,调用Binder驱动


          class ActivityManagerProxy implements IActivityManager
         {

         ......

         public int startActivity(IApplicationThread caller, Intent intent,
        String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
        IBinder resultTo, String resultWho,
        int requestCode, boolean onlyIfNeeded,
        boolean debug) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    intent.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeTypedArray(grantedUriPermi
      ......

Note:下文对于Binder通讯不在附加代码

这样通过AMS的远程服务代理,通知AMS,你现在给我准备我要启动某个软件的主Activity了

2.AMS通过Launcher传的IApplicationThread caller这个Binder告诉Launcher进程,我准备好了,你要进入Paused态了

3.Launcher通过Binder告诉AMS已经进入Paused态

4.AMS为即将运行的APP创建新进程,这个新进程会导入ActivityThread实例并运行其Main方法(同时说明,每个APP都有一个专属Process,都自带一个独有的ActivityThread主线程实例)

至此要启动APP的进程被创建

     ActivityThread.java中的 main这个函数

         ActivityThread thread = new ActivityThread();//在进程中创建一个ActivityThread实例,

          thread.attach(false); // 然后调用它的attach函数,接着就进入主线程消息循环了,直到最后进程退出。

Note:函数attach最终调用了ActivityManagerService的远程接口ActivityManagerProxy的attachApplication函数,传入的参数是mAppThread,这是一个ApplicationThread类型的Binder对象,它的作用是用来进行进程间通信的。

5.在ActivityThread的main方法中,再次通过AMS远程服务代理进行Binder通讯,讲自己的ApplicationThread这个Binder传给AMS,以供AMS后续与APP的通讯

6.AMS经过一系列处理,调用ApplicationThread(app.thread.scheduleLaunchActivity)通知APP进程,一切就绪,可以执行真正的MainActiviy启动了

7.ApplicationThread通过Handler发消息给主线程ActivityThread,主线程调用 handleLaunchActivity(r, null);
8. handleLaunchActivity(r, null);调用 performLaunchActivity(r, customIntent);
9. 收集要启动Activity的相关信息,主要package和component信息:
10. ClassLoader将xxx(包名).MainActivity类加载进来

               activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);

                        Instrumentation的newActivity方法内部实现是       return (Activity)cl.loadClass(className).newInstance();

至此要启动的activity被创建
11. 接下来是 makeApplication 创建Application对象,这是根据AndroidManifest.xml配置文件中的Application标签的信息来创建的

        java.lang.ClassLoader cl = getClassLoader();

        if (!mPackageName.equals("android")) {
            initializeJavaContextClassLoader();
        }

       a. ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);

       b.  app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);                              //通过类加载器创建Application

       c. instrumentation.callApplicationOnCreate(app);通过 instrumentation调用application实例的onCreate方法


        至此要启动APP的Application的Context以及Application示例被创建,并且Application的onCreate被调用

12.为Acticity创建上下文信息,并且将刚刚创建的ContextImpl通过Activity的attach赋值给Activity类的 继承自ContextWrapper的base成员(这样亦可以认为其属于activity类),

            Context appContext = createBaseContextForActivity(r, activity);
            CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
            Configuration config = new Configuration(mCompatConfiguration);
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                    + r.activityInfo.name + " with config " + config);

            activity.attach(appContext, this, getInstrumentation(), r.token,  
                    r.ident, app, r.intent, r.activityInfo, title, r.parent,
                    r.embeddedID, r.lastNonConfigurationInstances, config,
                    r.voiceInteractor);

       Note:
             这里,通过Activity的attach方法,ContextImpl与Activity建立的关联,同时在attach中还会完APP的Window创建并建立Activity与Window的关联,
             这样,以后当Window收到外部输入事件就会传递给Activity
            ContextWrapper具体实现即ContextImpl,Context的大部分功能都是ContextImpl实现的,比如context的抽像startActivty方法,具体实现在ContextImpl。

13. 最后在 performLaunchActivity中调用 mInstrumentation.callActivityOnCreate(activity, r.state);

14.handleLaunchActivity中 mInstrumentation.callActivityOnResume(this);这里调用了activity的onResume,并且通过Binder告诉AMS,已经resume了

总结:

    1. APP应用的进程创建由AMS进行,新的进程会导入android.app.ActivityThread类,并且执行它的main函数

    2.  可见,应用中的每个activity都对应一个context,因此每个app的总context数 == activity个数+service的个数 + 1 (application个数)

    3.  app的入口activity的创建在application之前,但是其oncreate调用却在application

    4.  activity生命周期的回调,最后都是通过mInstrumentation.callActivityOnXXX ,mInstrumentation在这里的作用是监控Activity与系统的交互操作,相当于是系统运行日志。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值