如何实例化 Android 活动(使用反射)?

2022-09-02 01:19:52

今天在Android采访中被问到这个问题。我回答了通常的,你知道,意图+开始活动,等等。面试官接着更尖锐地问道:

“是的,但它实际上在哪里实例化?你不会在任何地方调用新的活动”。

现在我想起来,我真的不知道。他暗示它使用了Java反射,但我对此没有太多经验,我只用它来访问Android SDK中的一些变量。

有人可以解释如何使用反射实例化活动,以及为什么?深入了解面试官在了解这一点时看到的价值的奖励点。


答案 1

当在主屏幕上单击应用程序的启动器图标时,在Android系统下会发生以下事件:

  • 主屏幕/启动器应用程序使用 startActivity()发送启动活动的意向(startActivity() 是 ActivityManager 的绑定器调用)
  • 活动管理器使用套接字向 Zygote 发送进程分叉请求。
  • Zygote分叉一个新的VM实例,该实例加载ActiveThread(活动线程管理应用程序进程中主线程的执行,在活动管理器请求时调度和执行活动,广播和其他操作。
  • ActivityThread具有用于应用程序的真正main()。
  • ActivityThread 调用应用的 onCreate()。

因此,ActivityThread 负责实例化 Activity(在 performLaunchActivity 方法内部)

解释:

如果您观察到堆栈跟踪:

android.app.Instrumentation.newActivity(Instrumentation.java:1021)
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2175)
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2261)

实例化新活动的代码:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ... //More code
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        StrictMode.incrementExpectedActivityCount(activity.getClass());
        r.intent.setExtrasClassLoader(cl);
        r.intent.prepareToEnterProcess();
        if (r.state != null) {
            r.state.setClassLoader(cl);
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(activity, e)) {
            throw new RuntimeException(
                "Unable to instantiate activity " + component
                + ": " + e.toString(), e);
        }
    }
    ... //More code
    return activity;
}

Instrumentation.java(类将在任何应用程序代码之前为您实例化)

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

答案 2

检查构造函数方法路径的简单方法是创建一个临时项目,重写构造函数并在其中放置断点。Activity

您应该能够遍历所有代码并找到您想要的确切内容。

enter image description here


推荐