返回介绍

送给你们的彩蛋

发布于 2025-02-28 12:35:45 字数 8199 浏览 0 评论 0 收藏 0

不要使用 startActivityForResult(intent,RESULT_OK)

这是因为 startActivity() 是这样实现的

public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
      startActivityForResult(intent, -1, options);
    } else {
      // Note we want to go through this call for compatibility with
      // applications that may have overridden the method.
      startActivityForResult(intent, -1);
    }
  }

public static final int RESULT_OK  = -1;

所以

startActivityForResult(intent,RESULT_OK) = startActivity()

你不可能从 onActivityResult() 里面收到任何回调。而这个问题是相当难以被发现的,就是因为这个坑,我工作一年多来第一次加班到 9 点 (ˇˍˇ)

一个 App 的程序入口到底是什么?

是 ActivityThread.main()。

整个 App 的主线程的消息循环是在哪里创建的?

是在 ActivityThread 初始化的时候,就已经创建消息循环了,所以在主线程里面创建 Handler 不需要指定 Looper,而如果在其他线程使用 Handler,则需要单独使用 Looper.prepare() 和 Looper.loop() 创建消息循环。

public static void main(String[] args) {

      ...ignore some code...  

    Looper.prepareMainLooper();

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

    if (sMainThreadHandler == null) {
      sMainThreadHandler = thread.getHandler();
    }

    AsyncTask.init();

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

    Looper.loop();

      ...ignore some code...  

 }

Application 是在什么时候创建的?onCreate() 什么时候调用的?

也是在 ActivityThread.main() 的时候,再具体点呢,就是在 thread.attach(false) 的时候。

看你的表情,不信是吧!凯子哥带你溜溜~

我们先看一下 ActivityThread.attach()

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    //普通 App 进这里
    if (!system) {

      ...ignore some code...  

      RuntimeInit.setApplicationObject(mAppThread.asBinder());
      final IActivityManager mgr = ActivityManagerNative.getDefault();
      try {
        mgr.attachApplication(mAppThread);
      } catch (RemoteException ex) {
        // Ignore
      }
       } else {
       //这个分支在 SystemServer 加载的时候会进入,通过调用
       // private void createSystemContext() {
       //  ActivityThread activityThread = ActivityThread.systemMain();
       //} 

       // public static ActivityThread systemMain() {
    //    if (!ActivityManager.isHighEndGfx()) {
    //      HardwareRenderer.disable(true);
    //    } else {
    //      HardwareRenderer.enableForegroundTrimming();
    //    }
    //    ActivityThread thread = new ActivityThread();
    //    thread.attach(true);
    //    return thread;
    //  }     
       }
  }

这里需要关注的就是 mgr.attachApplication(mAppThread),这个就会通过 Binder 调用到 AMS 里面对应的方法

@Override
  public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
      int callingPid = Binder.getCallingPid();
      final long origId = Binder.clearCallingIdentity();
      attachApplicationLocked(thread, callingPid);
      Binder.restoreCallingIdentity(origId);
    }
  }

然后就是

private final boolean attachApplicationLocked(IApplicationThread thread,
      int pid) {

       thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
          profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
          app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
          isRestrictedBackupMode || !normalMode, app.persistent,
          new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
          mCoreSettingsObserver.getCoreSettingsLocked());

      }

thread 是 IApplicationThread,实际上就是 ApplicationThread 在服务端的代理类 ApplicationThreadProxy,然后又通过 IPC 就会调用到

ApplicationThread 的对应方法

private class ApplicationThread extends ApplicationThreadNative {

  public final void bindApplication(String processName, ApplicationInfo appInfo,
        List<ProviderInfo> providers, ComponentName instrumentationName,
        ProfilerInfo profilerInfo, Bundle instrumentationArgs,
        IInstrumentationWatcher instrumentationWatcher,
        IUiAutomationConnection instrumentationUiConnection, int debugMode,
        boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
        Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
        Bundle coreSettings) {

         ...ignore some code...  

       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.enableOpenGlTrace = enableOpenGlTrace;
      data.restrictedBackupMode = isRestrictedBackupMode;
      data.persistent = persistent;
      data.config = config;
      data.compatInfo = compatInfo;
      data.initProfilerInfo = profilerInfo;
      sendMessage(H.BIND_APPLICATION, data);

       }

}

我们需要关注的其实就是最后的 sendMessage(),里面有函数的编号 H.BIND_APPLICATION,然后这个 Messge 会被 H 这个 Handler 处理

private class H extends Handler {

    ...ignore some code... 

   public static final int BIND_APPLICATION    = 110;

  ...ignore some code... 

   public void handleMessage(Message msg) {
      switch (msg.what) {
    ...ignore some code... 
     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;
    ...ignore some code... 
    }
 }

最后就在下面这个方法中,完成了实例化,拨那个企鹅通过 mInstrumentation.callApplicationOnCreate 实现了 onCreate() 的调用。

private void handleBindApplication(AppBindData data) {

 try {

       ...ignore some code... 

      Application app = data.info.makeApplication(data.restrictedBackupMode, null);
      mInitialApplication = app;

       ...ignore some code... 

      try {
        mInstrumentation.onCreate(data.instrumentationArgs);
      }
      catch (Exception e) {
      }
      try {
        mInstrumentation.callApplicationOnCreate(app);
      } catch (Exception e) {      }
    } finally {
      StrictMode.setThreadPolicy(savedPolicy);
    }
 }

data.info 是一个 LoadeApk 对象。

LoadeApk.data.info.makeApplication()

public Application makeApplication(boolean forceDefaultAppClass,
      Instrumentation instrumentation) {
    if (mApplication != null) {
      return mApplication;
    }

    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
      appClass = "android.app.Application";
    }

    try {
      java.lang.ClassLoader cl = getClassLoader();
      if (!mPackageName.equals("android")) {
        initializeJavaContextClassLoader();
      }
      ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
      app = mActivityThread.mInstrumentation.newApplication(
          cl, appClass, appContext);
      appContext.setOuterContext(app);
    } catch (Exception e) {    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

  //传进来的是 null,所以这里不会执行,onCreate 在上一层执行
    if (instrumentation != null) {
      try {
        instrumentation.callApplicationOnCreate(app);
      } catch (Exception e) {

      }
    }
    ...ignore some code... 

     }

    return app;
  }

所以最后还是通过 Instrumentation.makeApplication() 实例化的,这个老板娘真的很厉害呀!

static public Application newApplication(Class<?> clazz, Context context)
      throws InstantiationException, IllegalAccessException, 
      ClassNotFoundException {
    Application app = (Application)clazz.newInstance();
    app.attach(context);
    return app;
  }

而且通过反射拿到 Application 对象之后,直接调用 attach(),所以 attach() 调用是在 onCreate() 之前的。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文