这篇博客主要介绍Android在使用AppCompatActivity时遇到的一些出乎意料的问题,下面将问题及解决方案记录如下,便于查询。
问题
在使用Androidstudio开发中,默认创建的activity都继承自AppCompatActivity,如下图所示,然后在布局中使用也使用很简单的一个布局如下图所示。
public class MainActivity extends AppCompatActivity implementsView.OnClickListener{}
然后我想在别的工具类中(该工具类中有该view的引用)通过view.getContext 获得view所在activity的实例对象。于是乎有了如下的简单代码。
(1)MainActivity 中
Button button = (Button) findViewById(R.id.btn); button.setOnClickListener(MainActivity.this); if(button instanceof AppCompatButton){ Log.d("HHHHH","====button is appCompatButton===="); }
(2)工具类中
public static void getActivityInfo(View view){ Context context=view.getContext(); Log.d("HHHHH","getActivityInfo-getContext="+context); if(context instanceof Activity){ Activity activity= (Activity) context; Log.d("HHHHH","getActivityInfo-name="+activity.getClass().getSimpleName()); } }
结果日志是这样的。。。
what???
(1)我的Button怎么成了 AppCompatButton ??? (2)我的view.getContext得到的是TintContextWrapper,而不是Activity??这又是什么鬼.......
于是乎。。。查源码发现,我们的activity继承自AppCompatActivity时,也就是引用的是v7包时,我们的button就自动转为AppCompatButton 了(具体的可以参见AppCompatButton 源码注释)。同时在AppCompatButton 中我们的Context就变成了图中第二个框中的TintContextWrapper了。。。。
解决方案
原来在继承自AppCompatActivity时,Android底层会将我们应用的控件转为v7包中对应的控件,Context就被替换成了TintContextWrapper(他也继承自ContextWrapper)。所以我们可以通过如下代码获取想要的activity。
public static Activity getActivityFromView(View view) { if (null != view) { Context context = view.getContext(); while (context instanceof ContextWrapper) { if (context instanceof Activity) { return (Activity) context; } context = ((ContextWrapper) context).getBaseContext(); } } return null; }
其他和AppCompatActivity相关的问题可以参考如下文章。
Android 从 View 中获取 Activity 时遇到 TintContextWrapper cannot be cast to 的问题