Android中通过view.getContext获取Activity时得到TintContextWrapper的问题及解决

       这篇博客主要介绍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相关的问题可以参考如下文章。

AppCompatActivity

Android 从 View 中获取 Activity 时遇到 TintContextWrapper cannot be cast to 的问题

猜你喜欢

转载自blog.csdn.net/yyanjun/article/details/79896677