[关闭]
@act262 2017-05-24T14:25:59.000000Z 字数 4478 阅读 937

Application创建起源分析

AndroidSource


主要的类是ActivityThread,分为系统进程和我们的引用进程

系统进程:
SystemServer

  1. public static void main(String[] args) {
  2. new SystemServer().run();
  3. }
  4. private void run() {
  5. //...
  6. // Initialize the system context.
  7. createSystemContext();
  8. // Create the system service manager.
  9. mSystemServiceManager = new SystemServiceManager(mSystemContext);
  10. LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
  11. // Start services.
  12. startBootstrapServices();
  13. startCoreServices();
  14. startOtherServices();
  15. }
  1. public static ActivityThread systemMain() {
  2. // The system process on low-memory devices do not get to use hardware
  3. // accelerated drawing, since this can add too much overhead to the
  4. // process.
  5. if (!ActivityManager.isHighEndGfx()) {
  6. HardwareRenderer.disable(true);
  7. } else {
  8. HardwareRenderer.enableForegroundTrimming();
  9. }
  10. ActivityThread thread = new ActivityThread();
  11. thread.attach(true);
  12. return thread;
  13. }
  1. private void attach(boolean system){
  2. // ...
  3. // if system
  4. try {
  5. mInstrumentation = new Instrumentation();
  6. ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
  7. mInitialApplication = context.mPackageInfo.makeApplication(true, null);
  8. mInitialApplication.onCreate();
  9. } catch (Exception e) {
  10. throw new RuntimeException(
  11. "Unable to instantiate Application():" + e.toString(), e);
  12. }
  13. }

简化为

  1. LoadedApk packageInfo = new LoadedApk(this);
  2. ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
  3. mInitialApplication = packageInfo.makeApplication(true,null);
  4. mInitialApplication.onCreate();

普通Application创建的起源:
在系统进程的控制下进入main函数,
ActivityThread.main() -> ActivityThread.attach(fasle) [handleBindApplication] -> LoadedApk.makeApplication() -> Instrumentation.newApplication()

Application类的调用链:
Application() -> Application.attach() -> Application.attachBaseContext() -> Application.onCreate()

ActivityThread的attach方法区分是否系统的进程

  1. private void attach(boolean system) {
  2. }

LoadedApk类的方法

  1. public Application makeApplication(boolean forceDefaultAppClass,
  2. Instrumentation instrumentation) {
  3. if (mApplication != null) {
  4. return mApplication;
  5. }
  6. Application app = null;
  7. String appClass = mApplicationInfo.className;
  8. if (forceDefaultAppClass || (appClass == null)) {
  9. appClass = "android.app.Application";
  10. }
  11. try {
  12. java.lang.ClassLoader cl = getClassLoader();
  13. if (!mPackageName.equals("android")) {
  14. initializeJavaContextClassLoader();
  15. }
  16. ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
  17. app = mActivityThread.mInstrumentation.newApplication(
  18. cl, appClass, appContext);
  19. appContext.setOuterContext(app);
  20. } catch (Exception e) {
  21. if (!mActivityThread.mInstrumentation.onException(app, e)) {
  22. throw new RuntimeException(
  23. "Unable to instantiate application " + appClass
  24. + ": " + e.toString(), e);
  25. }
  26. }
  27. mActivityThread.mAllApplications.add(app);
  28. mApplication = app;
  29. if (instrumentation != null) {
  30. try {
  31. instrumentation.callApplicationOnCreate(app);
  32. } catch (Exception e) {
  33. if (!instrumentation.onException(app, e)) {
  34. throw new RuntimeException(
  35. "Unable to create application " + app.getClass().getName()
  36. + ": " + e.toString(), e);
  37. }
  38. }
  39. }
  40. // Rewrite the R 'constants' for all library apks.
  41. SparseArray<String> packageIdentifiers = getAssets(mActivityThread)
  42. .getAssignedPackageIdentifiers();
  43. final int N = packageIdentifiers.size();
  44. for (int i = 0; i < N; i++) {
  45. final int id = packageIdentifiers.keyAt(i);
  46. if (id == 0x01 || id == 0x7f) {
  47. continue;
  48. }
  49. rewriteRValues(getClassLoader(), packageIdentifiers.valueAt(i), id);
  50. }
  51. return app;
  52. }

Instrumentation

  1. static public Application newApplication(Class<?> clazz, Context context)
  2. throws InstantiationException, IllegalAccessException,
  3. ClassNotFoundException {
  4. Application app = (Application)clazz.newInstance();
  5. app.attach(context);
  6. return app;
  7. }

Application类的attach方法,实际上主要是调用到了attachBaseContext方法

  1. /* package */ final void attach(Context context) {
  2. attachBaseContext(context);
  3. mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
  4. }

所以我们的关注点在attachBaseContext方法中,该方法在其父类ContextWrapper中定义的.

  1. protected void attachBaseContext(Context base) {
  2. if (mBase != null) {
  3. throw new IllegalStateException("Base context already set");
  4. }
  5. mBase = base;
  6. }

子类重写的时候i.e.

  1. protected void attachBaseContext(Context base) {
  2. super.attachBaseContext(base);
  3. MultiDex.install(this);
  4. }

常用作动态部署,热更新机制在这里操作 i.e.

  1. @Override
  2. protected void attachBaseContext(Context context) {
  3. // ...
  4. createRealApplication();
  5. // This is called from ActivityThread#handleBindApplication() -> LoadedApk#makeApplication().
  6. // Application#mApplication is changed right after this call, so we cannot do the monkey
  7. // patching here. So just forward this method to the real Application instance.
  8. super.attachBaseContext(context);
  9. if (realApplication != null) {
  10. try {
  11. Method attachBaseContext =
  12. ContextWrapper.class.getDeclaredMethod("attachBaseContext", Context.class);
  13. attachBaseContext.setAccessible(true);
  14. attachBaseContext.invoke(realApplication, context);
  15. } catch (Exception e) {
  16. throw new IllegalStateException(e);
  17. }
  18. }
  19. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注