Activity运行上下文的创建过程

基于Android 7.0源码,分析Activity的运行上下文创建过程。

    在Activity启动过程中,是通过ActivityThread类的成员函数performLaunchActivity在应用程序进程中创建一个Activity实例,并且为它设置运行上下文环境,即为它创建一个ContextImpl对象。接下来,我们就从ActivityThread类的成员函数performLaunchActivity开始,分析一个Activity实例的创建过程,了解它的运行上下文环境的创建过程。

ActivityThread.performLaunchActivity
    Instrumentation.newActivity
    ActivityThread.createBaseContextForActivity
        ContextImpl.createActivityContext
            new ContextImpl
        ContextImpl.setOuterContext
    ActivityThread.attach
        ContextThemeWrapper.attachBaseContext
            ContextWrapper.attachBaseContext
ActivityThread.handleResumeActivity

#ActivityThread.performLaunchActivity

[===>frameworks/base/core/java/android/app/ActivityThread.java]

public final class ActivityThread {
  ...
  Instrumentation mInstrumentation;
  ...
  private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
      // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

      ActivityInfo aInfo = r.activityInfo;
      if (r.packageInfo == null) {
          r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                  Context.CONTEXT_INCLUDE_CODE);
      }

      ComponentName component = r.intent.getComponent();
      if (component == null) {
          component = r.intent.resolveActivity(
              mInitialApplication.getPackageManager());
          r.intent.setComponent(component);
      }

      if (r.activityInfo.targetActivity != null) {
          component = new ComponentName(r.activityInfo.packageName,
                  r.activityInfo.targetActivity);
      }

      Activity activity = null;
      try {
          java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
          activity = mInstrumentation.newActivity(
                  cl, component.getClassName(), r.intent);//创建Activity实例,此时并未真正进行初始化
          ......
      } catch (Exception e) {
          ......
      }

      try {
          Application app = r.packageInfo.makeApplication(false, mInstrumentation);

          ......

          if (activity != null) {
              Context appContext = createBaseContextForActivity(r, activity);//创建Activity运行上下文
              ......
              Configuration config = new Configuration(mCompatConfiguration);
              ......
              Window window = null;
              if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
                  window = r.mPendingRemoveWindow;
                  r.mPendingRemoveWindow = null;
                  r.mPendingRemoveWindowManager = null;
              }
              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);//此时进行activity实例的初始化工作

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

              activity.mCalled = false;
              //通过Instrumentation间接调用Activity的onCreate
              if (r.isPersistable()) {
                  mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
              } else {
                  mInstrumentation.callActivityOnCreate(activity, r.state);
              }
              ......
              r.activity = activity;//通过Instrumentation创建的Activity实例保存起来
              r.stopped = true;
              if (!r.activity.mFinished) {
                  activity.performStart();
                  r.stopped = false;
              }
              if (!r.activity.mFinished) {
                  //通过Instrumentation间接调用Activity的onRestoreInstanceState
                  if (r.isPersistable()) {
                      if (r.state != null || r.persistentState != null) {
                          mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                  r.persistentState);
                      }
                  } else if (r.state != null) {
                      mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                  }
              }
              if (!r.activity.mFinished) {
                  ......
              }
          }
          r.paused = true;

          mActivities.put(r.token, r);

      } catch (SuperNotCalledException e) {
          throw e;

      } catch (Exception e) {
          ......
      }

      return activity;
  }
  ...
}

    component描述的是需要启动Activity的组件类名,知道了这个类名后就可以调用ActivityThread类的成员变量mInstrumentation所描述一个Instrumentation对象的成员函数newActivity来创建一个Activity组件实例,并且保存在r.activity中。
    真正初始化一个activity实例对象是通过Activity类的attach函数进行的:

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

    初始化Activity实例对象需要一个Application对象app、一个ContextImpl对象appContext以及一个Configuration对象config,它们分别用来描述该Activity组件实例的应用程序信息、运行上下文环境以及配置信息。这里我们暂时只关注ContextImpl对象appContext的创建过程。
    函数就调用Activity组件实例activity的成员函数attach来将前面所创建的ContextImpl对象appContext以及Application对象app和Configuration对象config保存在它的内部,因此Activity组件实例activity就可以访问它的运行上下文环境信息了。
    最后,函数又通过调用ActivityThread类的成员变量mInstrumentation所描述一个Instrumentation对象的成员函数callActivityOnCreate来通知Activity组件实例activity,它已经被创建和启动起来了;调用Instrumentation对象的成员函数callActivityOnRestoreInstanceState类通知Activity组件实例activity来恢复数据。

    接下来我们就一步步分析。

##Instrumentation.newActivity

[===>frameworks/base/core/java/android/app/Instrumentation.java]

public class Instrumentation {
    ......
    public Activity newActivity(ClassLoader cl, String className,
        Intent intent)
        throws InstantiationException, IllegalAccessException,
        ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }
    ....
}

    参数cl描述的是一个类加载器,而参数className描述的要加载的类。以className为参数来调用cl描述的是一个类加载器的成员函数loadClass,就可以得到一个Class对象。由于className描述的是一个Activity子类,因此,当函数调用前面得到的Class对象的成员函数newInstance的时候,就会创建一个Activity子类实例,就是所要启动的Activity组件的。
    回到ActivityThread类的成员函数performLaunchActivity中,接下来就会调用ContextImpl类的构造函数来创建一个ContextImpl对象,用来描述正在启动的Activity组件的运行上下文信息。

##ActivityThread.createBaseContextForActivity

[===>frameworks/base/core/java/android/app/ActivityThread.java]

public final class ActivityThread {
    ......
    private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
        ......

        ContextImpl appContext = ContextImpl.createActivityContext(
                this, r.packageInfo, r.token, displayId, r.overrideConfig);
        appContext.setOuterContext(activity);
        Context baseContext = appContext;

        ......
        return baseContext;
    }
    ......
}

    这里会调用ContextImpl类的createActivityContext接口来创建Activity的运行上下文。

###ContextImpl.createActivityContext

[===>frameworks/base/core/java/android/app/ContextImpl.java]

class ContextImpl extends Context {
  ......
  static ContextImpl createActivityContext(ActivityThread mainThread,
          LoadedApk packageInfo, IBinder activityToken, int displayId,
          Configuration overrideConfiguration) {
      if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
      return new ContextImpl(null, mainThread, packageInfo, activityToken, null, 0,
              null, overrideConfiguration, displayId);
  }
  ......
}

    这个函数很简单,简单的一句话,直接创建并返回一个ContextImpl对象。

####new ContextImpl

[===>frameworks/base/core/java/android/app/ContextImpl.java]

class ContextImpl extends Context {
  ......

  private Context mOuterContext;
  ....
  private ContextImpl(ContextImpl container, ActivityThread mainThread,
          LoadedApk packageInfo, IBinder activityToken, UserHandle user, int flags,
          Display display, Configuration overrideConfiguration, int createDisplayWithId) {
      mOuterContext = this;

      ......
  }

  ......
}

    当一个ContextImpl对象是用来描述一个Activity组件的运行上下文环境时,那么它的成员变量mOuterContext指向的就是该Activity组件。这里创建ContextImpl对象时,并没有参数用来指明它是用来描述一个Activity组件的运行上下文环境,因此,这里暂时将它的成员变量mOuterContext指向它自己本身。回到执行ActivityThread.createBaseContextForActivity这里步,在创建并获取的刚创建的ContextImpl对象后,又调用了该对象的setOuterContext函数。

###ContextImpl.setOuterContext

[===>frameworks/base/core/java/android/app/ContextImpl.java]

class ContextImpl extends Context {
  ......

  private Context mOuterContext;
  ......

  final void setOuterContext(Context context) {
      mOuterContext = context;
  }

  ......
}

    看到木有?前脚还说没有说mOuterContext没有指明描述Activity组件的运行上下文,后脚就立即调用ContextImpl类的成员函数setOuterContext来设置前面所创建一个ContextImpl对象所关联的一个Activity组件,即正在启动的Activity组件。
    在具体的代码环境中,可以知道参数context描述的是一个正在启动的Activity组件,ContextImpl类的成员函数setOuterContext只是简单地将它保存在ContextImpl的成员变量mOuterContext中,以表明当前正在处理的一个ContextImpl对象是用来描述一个Activity组件的运行上下文环境的。
    回到前面ActivityThread类的成员函数performLaunchActivity中,接下来就会调用Activity类的成员函数attach来初始化正在启动的Activity组件。

##Activity.attach

[===>frameworks/base/core/java/android/app/Activity.java]

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback, WindowControllerCallback {
    ......

    private Application mApplication;
    ......

    /*package*/ Configuration mCurrentConfig;
    ......

    private Window mWindow;

    private WindowManager mWindowManager;
    ......

    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,
        Window window) {
        attachBaseContext(context);

        ......

        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        ......

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        ......
        mActivityInfo = info;
        ......

        mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
        if (mParent != null) {
            mWindow.setContainer(mParent.getWindow());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;
    }

    ......
}

    Activity.attach主要是对Activity的内部成员变量进行赋值。
    函数首先调用从父类ContextThemeWrapper继承下来的成员函数attachBaseConext来设置运行上下文环境,即将参数context所描述的一个ContextImpl对象保存在内部。
    函数接下来调用PolicyManager类的静态成员函数makeNewWindow来创建了一个PhoneWindow,并且保存在Activity类的成员变量mWindow中。这个PhoneWindow是用来描述当前正在启动的应用程序窗口的。这个应用程序窗口在运行的过程中,会接收到一些事件,例如,键盘、触摸屏事件等,这些事件需要转发给与它所关联的Activity组件处理,这个转发操作是通过一个Window.Callback接口来实现的。由于Activity类实现了Window.Callback接口,因此,函数就可以将当前正在启动的Activity组件所实现的一个Window.Callback接口设置到前面创建的一个PhoneWindow里面去,这是通过调用Window类的成员函数setCallback来实现的。
    在Android系统中,每一个应用程序窗口都需要由一个窗口管理者来管理,因此,函数再接下来就会调用前面所创建的一个PhoneWindow对象从父类Window继承下来的成员函数setWindowManager来为它设置一个合适的窗口管理者。这个窗口管理者设置完成之后,就可以通过调用Window类的成员函数getWindowManager来获得。获得这个窗口管理者之后,函数就将它保存在Activity类的成员变量mWindowManager中。这样,当前正在启动的Activity组件以后就可以通过它的成员变量mWindowManager来管理与它所关联的窗口。
    接下来,我们继续分析ContextThemeWrapper类的成员函数attachBaseConext的实现,以便可以继续了解一个应用程序窗口的运行上下文环境的设置过程。

###ContextThemeWrapper.attachBaseConext

[===>frameworks/base/core/java/android/view/ContextThemeWrapper.java]

public class ContextThemeWrapper extends ContextWrapper {
  ......
  @Override
  protected void attachBaseContext(Context newBase) {
      super.attachBaseContext(newBase);
  }
  ......
}

    ContextThemeWrapper类的成员函数attachBaseConext的实现很简单,它直接调用父类ContextWrapper的成员函数attachBaseConext来将参数newBase所描述的一个ContextImpl对象保存到父类ContextWrapper中去,继续分析ContextWrapper类的成员函数attachBaseConext的实现。

####ContextWrapper.attachBaseConext

[===>frameworks/base/core/java/android/content/ContextWrapper.java]

public class ContextWrapper extends Context {
    Context mBase;

    public ContextWrapper(Context base) {
        mBase = base;
    }

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

    public Context getBaseContext() {
        return mBase;
    }

    @Override
    public AssetManager getAssets() {
        return mBase.getAssets();
    }

    ......
}

    ContextWrapper类只是一个代理类,它只是简单地封装了对其成员变量mBase所描述的一个Context对象的操作。ContextWrapper类的成员函数attachBaseConext的实现很简单,它只是将参数base所描述的一个ContextImpl对象保存在成员变量mBase中。这样,ContextWrapper类就可以将它的功能交给ContextImpl类来具体实现。
    这一步执行完成之后,当前正在启动的Activity组件的运行上下文环境就已经设置好了,回到ActivityThread类的成员函数performLaunchActivity中,接下来就会调用Instrumentation类的成员函数callActivityOnCreate来通知当前正在启动的Activity组件,它已经创建和启动完成;也会调用Instrumentation类的成员函数callActivityOnRestoreInstanceState来通知当前正在启动的Activity组件恢复数据。

参考资料
Android应用程序窗口(Activity)的运行上下文环境(Context)的创建过程分析

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值