本文作者
作者:彭旭锐
链接:
https://www.jianshu.com/p/7d4bc7083a2f
本文由作者授权发布。
稳住,今天周末,来波小复习吧。
0 前言最近,在玩安卓上看到 每日一问:View#getContext() 一定会返回 Activity 对象么?直觉是:View 是由 Activity 管理的,那么 View#getContext() 一定是 Activity 了,事实真的如此吗?
其实这个问题主要还是考察应试者对于源码(包括:Context类型、LayoutInflater 布局解析、View 体系等)的熟悉度,在这篇文章里,我将跟你一起探讨。如果能帮上忙,请务必点赞加关注,这真的对我非常重要。
目录
1 问题分析
1.1 Context 有哪些?
首先,我们回顾一下 Context 以及它的子类,在之前的这篇文章里,我们曾经讨论过:《Android | 一个进程有多少个 Context 对象(答对的不多)》。
简单来说:Context 使用了装饰模式,除了 ContextImpl 外,其他 Context 都是 ContextWrapper 的子类。
我们熟悉的 Activity & Service & Application,都是 ContextWrapper 的子类。调用getBaseContext(),可以获得被代理的基础对象:
ContextWrapper.java
Context mBase;
public ContextWrapper(Context base) {
mBase = base;
}
public Context getBaseContext() {
return mBase;
}
需要注意的是,Activity 也是可以作为被代理的对象的,类似这样:
Activity activity = ...;
Context wrapper = new ContextThemeWrapper(activity, themeResId);
wrapper.startActivity(...); // OK
wrapper instanceOf Activity // false
这个时候,代理对象wrapper可以使用 Activity 的能力,可以用它 startActivity(),也可以初始化 View,然而它却不是 Activity。看到这里,我们似乎找到了问题的一点苗头了:getContext() 可能返回 Activity 的包装类,而不是 Activity。
1.2 问题延伸
网上讨论得比较多的,主要还是View#getContext()的返回值,在这篇文章里,我们将延伸一下,以下几种情况我都会归纳,以便帮助你建立更为清晰全面的认识:
View#getContext()
Fragment#getContext()
Window#getContext()
Dialog#getContext()
我们来看View#getContext()的源码,可以看到,View#getContext()返回值是在构造函数中设置的,源码里未发现其它