這篇博客主要介紹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 的問題