如何从View获取Activity?子类转换Context遇类型转换异常求助
Got it, let's break down why this error is happening and how to fix it cleanly. The crash occurs because the Context returned by getContext() isn't always a ContextWrapper (or an Activity). If your RequestRecord view is initialized with a non-Activity Context (like the app's global Application Context) or the underlying Context implementation is ContextImpl directly, your forced cast will fail immediately.
Here are two reliable solutions to resolve this:
1. Safely retrieve the Activity from any Context
Create a helper method to traverse the Context hierarchy and find the associated Activity (if it exists). This avoids unsafe direct casts and handles all valid Context types:
public class RequestRecord extends RelativeLayout { public RequestRecord(Context context) { super(context); init(context); } // Don't forget these constructors if you use this view in XML layouts public RequestRecord(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public RequestRecord(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { Activity activity = getActivityFromContext(context); if (activity != null) { ScrollView sv = (ScrollView) activity.findViewById(R.id.myReqList_scroll); // Proceed with your logic using the ScrollView here } else { // Handle the case where no Activity is linked (e.g., log a warning) Log.w("RequestRecord", "No Activity found for this view's Context"); } } private Activity getActivityFromContext(Context context) { while (context instanceof ContextWrapper) { if (context instanceof Activity) { return (Activity) context; } // Move up to the base Context if it's a wrapper but not an Activity context = ((ContextWrapper) context).getBaseContext(); } // Return null if no Activity exists in the Context hierarchy return null; } }
2. Enforce using an Activity Context (stricter but simpler)
If your RequestRecord view requires an Activity to function, you can make the dependency explicit by modifying the constructor to accept an Activity directly. This eliminates casting risks entirely:
public class RequestRecord extends RelativeLayout { public RequestRecord(Activity activity) { super(activity); ScrollView sv = (ScrollView) activity.findViewById(R.id.myReqList_scroll); // Your initialization logic here } // For XML inflation support, add checks to ensure the Context is an Activity public RequestRecord(Context context, AttributeSet attrs) { super(context, attrs); if (!(context instanceof Activity)) { throw new IllegalArgumentException("This view must be initialized with an Activity Context"); } ScrollView sv = (ScrollView) ((Activity) context).findViewById(R.id.myReqList_scroll); } }
Why your original code failed
Context has multiple implementations: Activity is a subclass of ContextWrapper, but ContextImpl (the low-level core Context implementation) is not. When you directly cast getContext() to ContextWrapper, you're making an unsafe assumption that the Context is always a wrapper—which isn't true in all scenarios. The helper method in the first solution safely navigates the Context hierarchy to find an Activity if it exists.
内容的提问来源于stack exchange,提问作者Ali Bagheri

