ContextThemeWrapper cannot be cast in AppCompatActivity

Viewed 1268

Cannot solve as:: java.lang.ClassCastException: android.view.ContextThemeWrapper cannot be cast to androidx.appcompat.app.AppCompatActivity.
Went through various sites but cannot solve my problem.

holder.ivPlace.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                AppCompatActivity activity = (AppCompatActivity) v.getContext();
                Fragment myFragment = new BookingDetailsFragment();
                activity.getSupportFragmentManager().beginTransaction().replace(R.id.bookingFragment, myFragment)
                        .addToBackStack(null).commit();



            }
        });

Layout is inflated in this way::

@NonNull
    @Override
    public BookingActivityAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.activity_booking_data, parent, false);
        ViewHolder viewHolder = new ViewHolder(view);
        return viewHolder;

    }
2 Answers

I think you can make use of the following snippet for your issue. But I would like to recommend you do not do so as such for two reasons mainly.

  • Since you explicitly need Activity only, why not send that through or even better implement an interface for callback.
  • What if tomorrow this will be changed, and there will be other context for View?
/**
 * Get activity instance from desired context.
 */
public static Activity getActivity(Context context) {
    if (context == null) return null;
    if (context instanceof Activity) return (Activity) context;
    if (context instanceof ContextWrapper) return getActivity(((ContextWrapper)context).getBaseContext());
    return null;
}

EDIT: Snippets for callback to activity

public interface MyAdapterListener {
        void onPlaceClick();
    }

And then when you are creating an instance of your Adapter you can pass it like this

public BookingActivityAdapter(MyAdapterListener myAdapterListener){
        this.myAdapterListener = myAdapterListener;
}

Just be sure to implement this interface in your activity. Then finally inside your onClick you can use this interface as follows

holder.ivPlace.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                myAdapterListener.onPlaceClick();

            }
        });

I know it's late but I resolved it by passing MyActivity.this instead of this or getApplicationContext().

Related