Application类的getApplicationContext()方法何时被调用?

12

我有一个Application类,在其中覆盖了getApplicationContext()方法。

我查看了Android源代码,但无法找到调用它的位置?

继承层次结构是:

Application -> ContextWrapper -> Context

public abstract Context getApplicationContext();

getApplicationContext()Context 类中的一个抽象方法,在 ContextWrapper 类中被覆盖重写。

@Override
public Context getApplicationContext() {
    return mBase.getApplicationContext();
}

mBase 是指向类型为 Context 的对象的引用,该对象在 ContextWrapper 构造函数中进行初始化,但根据代码 Application 类构造函数将 null 传递给 super()ContextWrapper 的构造函数。

public Application() {
    super(null);
}

现在传递上下文的唯一可能方式是通过:

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

但是也没有调用这个方法。请帮我找到 getApplicationContext() 方法被调用的位置。

注意:请不要在回答中提供任何指向这类问题的链接,因为我已经看过了每一个链接,但还是没有得到明确的答案。


在 grepcode 上查看 ContextImpl - Blackbelt
是的,我看过了。你能详细说明它是如何工作的吗? - CodeWarrior
3个回答

22
我猜问题更多是"在哪里为Application对象调用attachBaseContext()方法?"。
请参见Application.java
/**
 * @hide
 */
/* package */ final void attach(Context context) {
    attachBaseContext(context);
    mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}

如果你沿着调用链往上走一点,你会找到Instrumentation.newApplication() (Instrumentation.java),最后是LoadedApk.makeApplication() (LoadedApk.java),它们在应用程序启动时被调用。
    java.lang.ClassLoader cl = getClassLoader();
    ContextImpl appContext = new ContextImpl();
    appContext.init(this, null, mActivityThread);
    app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
    ...
    mApplication = app;

简而言之,提供给Application类的基础Context是在该方法中创建的ContextImpl实例。
如果你检查ContextImpl.getApplicationContext()
@Override
public Context getApplicationContext() {
    return (mPackageInfo != null) ? mPackageInfo.getApplication() : mMainThread.getApplication();
}

您会发现实际上它调用的是LoadedApk.getApplication()(因为mPackageInfoLoadedApk实例),这是之前提到的makeApplication()方法设置的mApplication字段。

简而言之,在所有这些设置完成后,Application.getApplicationContext()最终返回...同一个Application实例。 :)


Android的源代码在grepcode中是否不完整,因为根据grepcode,“attach()”没有提到“mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;”。来源:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/app/Application.java#70 - CodeWarrior
1
@AndroidWarrior,您正在查看发布于“2010年6月30日”的Android源代码版本“Version 2.2 r1.1”。请查看我在答案中分享的最新代码。 - Manish Mulimani
2
@AndroidWarrior 如果有疑问,始终要检查https://android.googlesource.com/platform/frameworks/base.git/+/master(或更通用的https://android.googlesource.com/),这是官方的AOSP存储库。 Github和grepcode都是镜像,而且不总是完全同步。 - matiash

6

0
 public class ContactManagerApplication extends Application {
public static Context context = null;

 @Override
public void onCreate() {
    super.onCreate();
    Log.d("@gaurav", getApplicationContext()+"");
    context = getApplicationContext();

}

1
请详细阐述您的答案。解释解决方案是什么,而不仅仅是粘贴代码。 - Luceos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接