2017.6.6 TintContextWrapper cannot be cast to ...Activity

問題描述:

如果一個 View 繪制于某個 Activity 的 ContentView 上, 那它的 Context 一定是和這個 Activity 相關聯的. 因此我們想在 View 中直接用 Activity 方法時 (最常用的應該就是 Activity.startActivity() 方法了), 不必再向 View 中傳遞 Activity 對象.
一般在 View 中獲取這個 Activity 對象都是簡單的用下面代碼就可以了:

Activity activity = (Activity) getContext();

但在 View 繼承自 AppCompat 系的 View 時 (比如 AppCompatTextView, AppCompatImageView), 下面方法可能會得到下面異常:

  View view1 = ((Activity) view.getContext()).getLayoutInflater().inflate(R.layout.date_dialog, null);
**java.lang.ClassCastException: android.support.v7.widget.TintContextWrapper cannot be cast to ...Activity**

問題解決:
知道原因就簡單了. 可以簡單的用 ContextWrapper.getBaseContext()
得到這個 Activity. 但其實一層層的從 ContextWrapper 中把 Activity 剝出來更保險:

/**
     * try get host activity from view.
     * views hosted on floating window like dialog and toast will sure return null.
     * @return host activity; or null if not available
     */
    public static Activity getActivityFromView(View view) {
        Context context = view.getContext();
        while (context instanceof ContextWrapper) {
            if (context instanceof Activity) {
                return (Activity) context;
            }
            context = ((ContextWrapper) context).getBaseContext();
        }
        return null;
    }

如上方法可以通用的解決從 View 中獲取 Activity 的問題.
事實上, 谷歌 v7 包中的 Android.support.v7.app.MediaRouteButton
就是這么干的.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容