我只是出于兴趣而调查了Android sources。我发现Context
是一个抽象类,抽象方法:
public abstract Context getApplicationContext();
导致ContextWrapper.java
方法实施的Context.java
扩展getApplicationContext()
:
@Override
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
但mBase
是对Context
类型的对象的引用,该对象在ContextWrapper
的构造函数中初始化:
public ContextWrapper(Context base) {
mBase = base;
}
所以这个mBase
引用是指abstract
类吗?
好吧,我只是不明白当你从getApplicationContext()
拨打Activity
时执行的代码在哪里。
答案 0 :(得分:15)
这是多态性的一个有趣例子。
只要您的base
扩展Context
,就必须提供getApplicationContext()
的实施,在ContextWrapper
的情况下,您需要提供此处提供的代码。有这个实现,the one in ContextImpl
。
在阅读您提供的代码时,请务必注意以下几点:ContextWrapper
本身扩展Context
,但它也需要Context
作为输入(可能是{ {1}},或ContextWrapper
,Service
或Application
)。 Activity
并不关心它是哪种类型;它只知道他们有一个方法ContextWrapper
,它想在被问到时调用该方法。 (例如,它可以传递给另一个getApplicationContext
,但因为所谓的ContextWrapper
在其构造函数中也需要ContextWrapper
,这只会增加另一级别的嵌套。)
Context
班级调用Application extends ContextWrapper
,这意味着super(null)
如果将其留下getApplicationContext()
将会抛出NullPointerException
- 但是,ContextWrapper
它也可以由attachBaseContext(Context)
设置,这就是它变得有趣的地方。
Activity
和Application
都有方法attach(Context [...other stuff])
。他们每个人都使用传入的attachBaseContext()
调用Context
。
Instrumentation
课程中,您会找到android.app.Instrumentation.newApplication()
,其中ContextImpl
已创建,并传递到Application
。 ActivityThread
课程中,您会找到handleBindApplication
,其中ContextImpl
会将Activity
作为其根Context
传递给LoadedApk
。makeApplication
课程中,您会找到ContextImpl
,其中Application
会传递给mBase
。 Here是它所称的地方。因此,在一天结束时,ContextImpl
通常最终为{{1}}。
我在查找所有这些内容时看到的潜在有用链接: