如果不是,那什么场景下不是。
更多问答 >>
-
每日一问 有没有使用过 DataBinding ,有什么优点、缺点,遇到过哪些坑?
2019-06-26 00:23 -
每日一问 | 为什么属性动画移动一个控件后,目标位置仍然能响应用户事件?
2019-06-27 23:50 -
每日一问 ANR的产生的原理是什么,AMS中涉及ANR的代码有哪些?
2019-06-30 22:33 -
每日一问 对于SharedPreferences你觉得有什么优缺点?
2019-07-02 23:35 -
每日一问 | getWidth, getMeasuredWidth 有什么区别?
2019-07-05 00:48 -
每日一问 详细的描述下自定义 View 测量时 MesureSpec.UNSPECIFIED
2019-06-20 00:26 -
每日一问 自定义 ViewGroup 的时候,关于 LayoutParams 有哪些注意事项?
2019-06-15 21:09 -
每日一问 gradle Transform API 和 Annotation Processor各有什么使用场景?能否相互替换与补充。
2019-06-13 21:54 -
2019-05-29 12:23
-
每日一问 View的onAttachedToWindow ,onDetachedFromWindow 调用时机,使用场景是什么?
2019-05-26 19:19

不一定是。
那么,在什么场景下不是呢:
除了自己手动传不是Activity的Context进去之外,还有一种情况,就是:
当使用AppCompatActivity 时。
我们都知道,在这个Activity里的原生控件(如TextView, ImageView等等),当在LayoutInflater中把xml解析成View的时候,最终会经过AppCompatViewInflater的createView方法: 把这些原生控件都变成 AppCompatXXX 一类的! 比如TextView的话,就会变成AppCompatTextView, ImageView会变成AppCompatImageView 。
当然了,这些AppCompat开头的,都是继承于被转换的那个对象的。那重点就在这些AppCompat开头的控件了,随便打开一个他们源码,比如AppCompatImageView,打开之后会看到: 当它们调用父类的构造方法时,调用了TintContextWrapper的wrap方法,并把Context传进去了!看这个方法的名字, wrap很明显就是包装的意思嘛,点进去wrap方法看,还会看到首先调用了shouldWrap方法: 检查一下这个context应不应该被包装。如果方法返回true, 会创建一个TintContextWrapper对象(把Context传进去),然后返回,那么,这时候,当我们调用这个View的getContext方法,自然就不是Activity了,而是它传进去的TintContextWrapper。那么,究竟什么情况下,shouldWrap方法会返回true呢(Context会被包装), 点开看下源码:
得出结论:
当运行在5.0系统版本以下的手机,并且Activity是继承自AppCompatActivity的,那么View的getConext方法,返回的就不是Activity而是TintContextWrapper.
小缘请正面接受鸿洋的夸奖
讲的真好,总结的真好
厉害厉害
先做个大胆的猜想, View.getContext() 不可能一定返回 Activity 对象,不然干啥不用 View.getActivity() 方法来代替。
至于什么情况下不是,我们必须得去看看源码是怎么回事。好吧,当我检查后,发现 @陈小缘啦啦啦 已经说完了。 事实就是他(她)说的那样。
不一定都是Activity.
Activity中setContentView时一定是Activity;通过 new View、View.inflate、LayoutInflater.inflate 这几种方式添加View,我们传参时传的是什么context, View中的就是什么Context.Activity中setContentView时为什么一定是Activity
setContentView 时,其加载过程为 Activity.setContentView -> PhoneWindow.setContentView -> LayoutInflater.inflate -> LayoutInflater.createViewFromTag -> LayoutInflater.onCreateView -> LayoutInflater.createView最终在createView方法中来实例化xml文件中的View,这里可以看到传参的context是LayoutInflater的context,而LayoutInflater是在PhoneWindow中创建的,其context是PhoneWindow的context, PhoneWindow的context是Activity.所以,以setContentView方式来加载View,View的context一定是Activity.另外三种方式为什么就按传的内容呢
new View就毋庸置疑了,很明显是直接传的context。另外两种也都是通过LayoutInflater加载的,View的context就是LayoutInflater的context,也就是我们创建LayoutInflater时的传参了。补充一点,我们有时候会遇到将context强转为Activity的情况我们应该怎么处理呢? 事实上当运行在5.0系统版本以下的手机,并且Activity是继承自AppCompatActivi ...查看更多
补充一点,我们有时候会遇到将context强转为Activity的情况我们应该怎么处理呢? 事实上当运行在5.0系统版本以下的手机,并且Activity是继承自AppCompatActivity的,那么View的getConext方法,返回的就不是Activity而是`TintContextWrapper`. 但是你说的View的底层容器其实都是activity是对的,因为TintContextWrapper的`getBaseContext` 确实还是activity。 而题目问的是view.getContext一定是activity吗,而不是底层容器最后是不是activity。 那么我们就可以用以下代码实现了。。 ``` if (context instanceof ContextWrapper) { if(((ContextWrapper) context).getBaseContext() instanceof Activity) } ``` 这样我们就可以拿到activity了
除了 TintContextWrapper,还有的情况直接写了一篇文章,感兴趣的可以看看,
每日一问:View.getContext() 一定会返回 Activity 对象么?
链接是:https://mp.weixin.qq.com/s/5Xj6O9wV_EnynpdnB5mJ5A
补充一点,我们有时候会遇到将context强转为Activity的情况我们应该怎么处理呢?
事实上当运行在5.0系统版本以下的手机,并且Activity是继承自AppCompatActivity的,那么View的getConext方法,返回的就不是Activity而是`TintContextWrapper`. 但是你说的View的底层容器其实都是activity是对的,因为TintContextWrapper的`getBaseContext` 确实还是activity。 而题目问的是view.getContext一定是activity吗,而不是底层容器最后是不是activity。 那么我们就可以用以下代码实现了。。``` if (context instanceof ContextWrapper) { if(((ContextWrapper) context).getBaseContext() instanceof Activity) } ```这样我们就可以拿到activity了按我理解
在activity通过setView方式,getConext是activity
在fragment通过LayoutInflater inflater方式setView也是activity如果是悬浮窗、通过new View(appliaction)方式就不是activity
LayoutInflater的也可以换的...
答案:可能是Application、Service、ContextImpl、ContextWrapper、Activity的任何一个。
原文链接:《Android | View & Fragment & Window 的 getContext() 一定返回 Activity 吗?》
1.1 Context 有哪些?
首先,我们回顾一下 Context 以及它的子类,在之前的这篇文章里,我们曾经讨论过:《Android | 一个进程有多少个 Context 对象(答对的不多)》。简单来说:Context 使用了装饰模式,除了 ContextImpl 外,其他 Context 都是 ContextWrapper 的子类。
我们熟悉的 Activity & Service & Application,都是 ContextWrapper 的子类。调用
getBaseContext(),可以获得被代理的基础对象:ContextWrapper.java需要注意的是,Activity 也是可以作为被代理的对象的,类似这样:
这个时候,代理对象
wrapper可以使用 Activity 的能力,可以用它startActivity(),也可以初始化 View,然而它却不是 Activity。看到这里,我们似乎找到了问题的一点苗头了:getContext() 可能返回 Activity 的包装类,而不是 Activity。为避免篇幅过长,第 2 ~ 6 节详见《Android | View & Fragment & Window 的 getContext() 一定返回 Activity 吗?》,有帮助请给点赞关注鼓励一下吧!
应用窗口的Dialog的view的getContext不是
答案是: 不一定是。
关键是取决于你传入的Context是什么,无论是xml还是代码声明的View 最终都会走View 的构造方法创建,通过源码很明确的可以知道,你构造方法传入的是谁,你的getContext 就是谁。
对于View的创建区分两种形式,先说简单的直接new,这种就比较明显了,你new 的谁就是谁,无论是Application or Activity or ContextWrapper 类都是可以的; 另一种就是xml的形式,这个底层使用的LayoutInflater 去加载解析的,对于构建View来说,View的context 取决于LayoutInflater内的context(此处细节看LayoutInflater的实现代码,太多就不贴了),对于LayoutInflater来说其初始化的方法使用LayoutInflater.from(context) 的形式获得(此处细节看下Context的getSystemServiceName的实现),你如果传入Activity 则你的LayoutInflater内的context就是Activity (Activity 重写了getSystemServiceName的方法,会将自己的Context 传入),如果你传入的是Application的,则会使用Application的,默认Activity内的布局都是传入的Activity的所以你这个时候生成的View 的getContext 都是Activity 的。
上面已经清楚的说明View的context 取决于你传的什么,具体细节不清晰的可以再看下回复然后结合源码去看(Activity、ContextImpl、LayoutInflater、SystemServiceRegistry、PhoneLayoutInflater)。
肯定不一定是吧,那比如添加到window中的,和桌面控件和通知的View都是么?
尤其是桌面控件的 \手动抠鼻
看完陈小缘的回答,自己再结合代码看了一下,发现几个问题。首先,TintContextWrapper是一个包装类,它的父类是ContextWrapper,而这个看完陈小缘的回答,自己再结合代码看了一下,发现几个问题。首先,TintContextWrapper是一个包装类,它的父类是ContextWrapper,而这个类又是Context的子类,这个类的作用就是在于在有新功能时不改变顶层Context,TintContextWrapper就是一个很好的例子。在TintContextWrapper出现之前,在View中出现的都是ContextWrapper,那么按照回答中的理论,getContext也获取的不是Context了,其实并不然,因为ContextWrapper中有Context的成员变量,在View中获取Context的时候都会直接调用getBaseContext方法,而这个方法得到的就是构造方法中设定的Context。
我觉得我们还是应该从源头去寻找答案,问题中是问View中getContext,既然如此应该直接去这里查看,getContext中直接返回了mContext的成员变量,而这个变量是在构造方法中赋值的,由此我们可以寻找,什么时候会把Context赋值?就是说,什么时候会生成一个View?而这些View出现在哪里?显然在Activity,Dialog或者PopupWindow中,而这些View的底层容器其实都是Activity,我认为View中的getContext一定返回的是Activity对象。问出这种问题大概率时不一定,然后看小缘同志的答案啦啦啦