记一次View.getContext()遇到的大坑

lqlwoaini 7年前
   <p>有的时候不能盲目自信,不然会踩到大坑啊,哎。。还是因为太菜了。</p>    <p>事情的经过是这样子滴: 有一个特殊条件,需要把View的context强转为Activity。</p>    <p>大概是这样子的:</p>    <pre>  imageView.context as Activity     </pre>    <p>这个时候我是比较确信这个view的context一定是Activity的,所以没有加以下判断。</p>    <pre>  if (imageView.context is Activity)        </pre>    <p>然后坑就来了。。 4.x该蹦的全崩了。。当时我的心情犹如股市大跌,想要去跳楼。</p>    <h2>确信的理由</h2>    <p>为什么我当时认为这个context一定是Activity呢,其实不是没有理由的。因为我的imageView是写在xml里的,大家都知道,setContextView(),其实就是PhoneWindow的setContentView():</p>    <p><img src="https://simg.open-open.com/show/8b64c9f2fa9b0ea50e10538b2da6a79f.png"></p>    <p>发现这个view是LayoutInflater解析xml反射出来的。view的context就是LayoutInflater的mContext:</p>    <p><img src="https://simg.open-open.com/show/a28f25f9cd0b71b22493640af2cec89f.png"></p>    <p>这个LayoutInflater的context是PhoneWindow传进去的:</p>    <p><img src="https://simg.open-open.com/show/7714f30660a2a10900f5db0a060d2106.png"></p>    <p>PhoneWindow的context就是Activity的this:</p>    <p><img src="https://simg.open-open.com/show/e64d4597309cb2f10dc1fcce203dc31c.png"></p>    <p>所以,也就是说,一个写在xml里的View,他的context就是Activity。 源码是这样告诉我的。可是为什么4.x都崩了呢,4.x的view的context到底是什么呢?</p>    <h2>刨根问底</h2>    <p>如果你听过LayoutInflaterFactory,那么大概就能想出是什么原因了,代码是不会骗人的,可是为什么View的context变了呢,那只能是有其他代码在搞鬼。所有Appcompat的Activity,创建View的时候,都会对基本View做一个风格的包装,也就是说ImageView会变成AppcompatImageView。 那么实际上,imageView.context 是AppcompatImageView的getContext().</p>    <p>研究发现,AppcompatImageView并没有重写getContext()方法,那么到底怎么回事呢,直接看他的构造器:</p>    <p><img src="https://simg.open-open.com/show/a92c1d413579dae2c590ec2f39f0094e.png"></p>    <p>卧槽,坑爹呢这是! 发现即使context传进来是个activity,也回被包装成TintContextWrapper。</p>    <p>那么为什么5.0以上系统,获得的还是一个Activity呢?</p>    <p>继续看:</p>    <p><img src="https://simg.open-open.com/show/20314099982e530785cd68d70ccde929.png"></p>    <p><img src="https://simg.open-open.com/show/57d1d599976de6ba8aa8ae88fe09f7a6.png"></p>    <p>nnd,原来如此,看样子是v7包为了能加载到一些特殊资源,给包裹成了TintContextWrapper。 所以强转出错!!!</p>    <p>这个故事告诉我们,就算你有绝对的自信,你也不能保证你百分百正确,该遵守的一些优良习惯,还是要养成的。。</p>    <p> </p>    <p>来自:http://androidwing.net/index.php/225</p>    <p> </p>