DialogFragment 调用失败

Posted

技术标签:

【中文标题】DialogFragment 调用失败【英文标题】:DialogFragment call failed 【发布时间】:2021-04-20 01:29:15 【问题描述】:

当你点击CardView时,应该会出现DialogFragment,但是应用程序崩溃了,在日志中写下以下内容

 Process: com.example.testfuntura, PID: 15385
    java.lang.ClassCastException: android.view.ContextThemeWrapper cannot be cast to androidx.appcompat.app.AppCompatActivity
        at com.example.testfuntura.Attraction.AdapterAttractionsPackageOffer.lambda$onBindViewHolder$0(AdapterAttractionsPackageOffer.java:56)
        at com.example.testfuntura.Attraction.-$$Lambda$AdapterAttractionsPackageOffer$4cZEQxk2beWA40yZmNkr6ZJp7o8.onClick(lambda)
        at android.view.View.performClick(View.java:5692)
        at android.view.View$PerformClick.run(View.java:22596)

我的Adapter

public class AdapterAttractionsPackageOffer extends RecyclerView.Adapter<AdapterAttractionsPackageOffer.AttractionsViewHolderPackageOffer> 
    public ArrayList<ItemPOA> mFavList;

    public AdapterAttractionsPackageOffer(ArrayList<ItemPOA> favList) 
        mFavList = favList;
    

    @NonNull
    @Override
    public AttractionsViewHolderPackageOffer onCreateViewHolder(ViewGroup parent, int viewType) 
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_attraction_package_offer, parent, false);
        return new AttractionsViewHolderPackageOffer(v);
    

    public static class AttractionsViewHolderPackageOffer extends RecyclerView.ViewHolder 
        public ImageView card_image_1;
        public TextView Package_offer_title;
        public CardView Card;

        public AttractionsViewHolderPackageOffer(View itemView) 
            super(itemView);
            Card = itemView.findViewById(R.id.att_po);
            card_image_1 = itemView.findViewById(R.id.img_po);
            Package_offer_title = itemView.findViewById(R.id.tex);

        
    
    @SuppressLint("LongLogTag")
    @Override
    public void onBindViewHolder(AttractionsViewHolderPackageOffer holder, int position) 
        ItemPOA currentItem = mFavList.get(position);
        holder.Package_offer_title.setText(currentItem.get_Package_offer_title());
        holder.Card.setOnClickListener(v -> 
            DialogPOA dialog = new DialogPOA();
            dialog.show(((AppCompatActivity) v.getContext()).getSupportFragmentManager(), "item");
            Bundle bundle1 = new Bundle();

            bundle1.putString("title_po", currentItem.get_Package_offer_title());
            bundle1.putString("description_po", currentItem.get_Package_offer_description());
            bundle1.putString("cost_po", currentItem.get_Package_offer_cost());
            dialog.setArguments(bundle1);
        );
        holder.getAdapterPosition();
    

    @Override
    public int getItemCount() 
        return mFavList.size();
    

我有一个类似的Adapter,但是当被调用时,一切正常,也就是说,问题不在于DialogFragment,因为从另一个片段调用时一切正常。

Fragment 所在的CardView

public class FragmentAtt extends Fragment 
    ArrayList<ItemPOA> mFavList;

    String URL = "http://qqqqqqqqq.mcdir.ru/dbpo.php";
    RecyclerView mRec;
    RecyclerView.LayoutManager recyclerViewlayoutManager;
    RecyclerView.Adapter recyclerViewadapter;

    //ImageView GET_PO_IMG;
    String GET_PO_TITLE = "title_po";
    String GET_PO_DESCRIPTION = "description_po";
    String GET_PO_COST = "cost_po";


    RequestQueue requestQueue;
    JsonArrayRequest jsonArrayRequest;

    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
        View view = inflater.inflate(R.layout.fragment_test_attraction, container, false);
        TabLayout tabLayout = view.findViewById(R.id.tab);
        ViewPager viewPager = view.findViewById(R.id.pager);
        setupViewPager(viewPager);

        tabLayout.setupWithViewPager(viewPager);
        return view;
    

    @Override
    public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) 

        mRec = requireView().findViewById(R.id.rec_po);

        mFavList = new ArrayList<>();

        recyclerViewadapter = new AdapterAttractionsPackageOffer(mFavList);

        recyclerViewlayoutManager = new LinearLayoutManager(getContext());

        mRec.setHasFixedSize(true);
        mRec.setLayoutManager(recyclerViewlayoutManager);
        mRec.setAdapter(recyclerViewadapter);
        JSON_DATA_WEB_CALL2_RINK();

        //recyclerViewlayoutManager = new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false);

        //SnapHelper snapHelper = new GravitySnapHelper(Gravity.START);
        //snapHelper.attachToRecyclerView(mRec);
    

    private void setupViewPager(ViewPager viewPager) 
        PagerAdapter adapter = new PagerAdapter(getChildFragmentManager());
        adapter.addFragment(new FragmentAttractionRecyclerView(), "Аттракционы");
        adapter.addFragment(new FragmentAttractionRecyclerView(), "Видеоигры");
        viewPager.setAdapter(adapter);

    

    public void JSON_DATA_WEB_CALL2_RINK() 
        jsonArrayRequest = new JsonArrayRequest(URL,
                this::JSON_PARSE_DATA_AFTER_WEBCALL_RINK,
                error ->
                        Log.e("Volley", error.toString())) 
            @Override
            protected Response<JSONArray> parseNetworkResponse(NetworkResponse response) 
                try 
                    Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
                    if (cacheEntry == null) 
                        cacheEntry = new Cache.Entry();
                    
                    final long cacheExpired = 24 * 60 * 60 * 1000; // in 24 hours this cache entry expires completely
                    long now = System.currentTimeMillis();
                    final long ttl = now + cacheExpired;
                    cacheEntry.data = response.data;
                    cacheEntry.softTtl = now;
                    cacheEntry.ttl = ttl;
                    String headerValue;
                    headerValue = response.headers.get("Date");
                    if (headerValue != null) 
                        cacheEntry.serverDate = HttpHeaderParser.parseDateAsEpoch(headerValue);
                    
                    headerValue = response.headers.get("Last-Modified");
                    if (headerValue != null) 
                        cacheEntry.lastModified = HttpHeaderParser.parseDateAsEpoch(headerValue);
                    
                    cacheEntry.responseHeaders = response.headers;
                    final String jsonString = new String(response.data,
                            HttpHeaderParser.parseCharset(response.headers));
                    return Response.success(new JSONArray(jsonString), cacheEntry);
                 catch (UnsupportedEncodingException | JSONException e) 
                    return Response.error(new ParseError(e));
                
            
        ;
        requestQueue = Volley.newRequestQueue(requireContext());
        requestQueue.add(jsonArrayRequest);
    

    public void JSON_PARSE_DATA_AFTER_WEBCALL_RINK(JSONArray array) 
        mFavList.clear();
        for (int i = 0; i < array.length(); i++) 
            ItemPOA GetDataAdapter2 = new ItemPOA();
            JSONObject json;
            try 
                json = array.getJSONObject(i);
                GetDataAdapter2.set_Package_offer_title(json.getString(GET_PO_TITLE));
                GetDataAdapter2.set_Package_offer_description(json.getString(GET_PO_DESCRIPTION));
                GetDataAdapter2.set_Package_offer_cost(json.getString(GET_PO_COST));
             catch (JSONException e) 
                e.printStackTrace();
            
            mFavList.add(GetDataAdapter2);
        
        recyclerViewadapter = new AdapterAttractionsPackageOffer(mFavList);
        mRec.setAdapter(recyclerViewadapter);
    

一个具有相同功能的Adapter,但为什么会起作用,解释一下区别?

public class AdapterSkatingRinkSchedule_2 extends RecyclerView.Adapter<AdapterSkatingRinkSchedule_2.SkatingRinkScheduleViewHolder> 
    public ArrayList<ItemSkatingRinkSchedule_2> mSkatingRinkScheduleList;

    public AdapterSkatingRinkSchedule_2(ArrayList<ItemSkatingRinkSchedule_2> SkatingRinkScheduleList) 
        mSkatingRinkScheduleList = SkatingRinkScheduleList;
    

    @NonNull
    @Override
    public SkatingRinkScheduleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_srs, parent, false);
        return new SkatingRinkScheduleViewHolder(v);
    

    public static class SkatingRinkScheduleViewHolder extends RecyclerView.ViewHolder 
        public TextView number_srs, start_time_srs, end_time_srs, cost_1_srs, cost_2_srs;
        public LinearLayout ll_main;


        public SkatingRinkScheduleViewHolder(View itemView) 
            super(itemView);
            ll_main = itemView.findViewById(R.id.ll_main);
            number_srs = itemView.findViewById(R.id.number_srs);
            start_time_srs = itemView.findViewById(R.id.start_time_srs);
            end_time_srs = itemView.findViewById(R.id.end_time_srs);
            cost_1_srs = itemView.findViewById(R.id.cost_1_srs);
            cost_2_srs = itemView.findViewById(R.id.cost_2_srs);
        
    
    @SuppressLint("LongLogTag")
    @Override
    public void onBindViewHolder(SkatingRinkScheduleViewHolder holder, int position) 
        ItemSkatingRinkSchedule_2 currentItem = mSkatingRinkScheduleList.get(position);
        holder.number_srs.setText(currentItem.get_session_number());
        holder.start_time_srs.setText(currentItem.get_session_start());
        holder.end_time_srs.setText(currentItem.get_session_end());
        holder.cost_1_srs.setText(currentItem.get_weekdays());
        holder.cost_2_srs.setText(currentItem.get_weekends_and_holidays());
        holder.ll_main.setOnClickListener(v -> 
            DialogSkatingRinkSchedule dialogSRS = new DialogSkatingRinkSchedule();
            dialogSRS.show(((AppCompatActivity) v.getContext()).getSupportFragmentManager(), "item");
            Bundle bundle2 = new Bundle();

            bundle2.putString("number", currentItem.get_session_number());
            bundle2.putString("start", currentItem.get_session_start());
            bundle2.putString("end", currentItem.get_session_end());
            bundle2.putString("w", currentItem.get_weekdays());
            bundle2.putString("wah", currentItem.get_weekends_and_holidays());
            dialogSRS.setArguments(bundle2);
        );
        holder.getAdapterPosition();
    

    @Override
    public int getItemCount() 
        return mSkatingRinkScheduleList.size();
    

【问题讨论】:

【参考方案1】:

java.lang.ClassCastException: android.view.ContextThemeWrapper 无法转换为 androidx.appcompat.app.AppCompatActivity

在这里,您将context 转换为AppCompatActivity,但实际上是Activity is not a Context

你有两个选择来解决这个问题:

    第一个选项:在持有RecyclerView的activity/fragment之间创建一个监听器接口,在那个activity中实现它,并在CardViewonClickListeneronClick()内触发它的回调回调。

    第二个选项: 更改AdapterAttractionsPackageOffer 适配器的构造函数签名以接受FragmentManager 实例;将其保存为如下所示的类字段,并将其反映在适配器的实例化上

public class AdapterAttractionsPackageOffer extends RecyclerView.Adapter<AdapterAttractionsPackageOffer.AttractionsViewHolderPackageOffer> 
    public ArrayList<ItemPOA> mFavList;
    
    private FragmentManager fragmentMgr;
    
    public AdapterAttractionsPackageOffer(ArrayList<ItemPOA> favList, FragmentManager fManger) 
        mFavList = favList;
        fragmentMgr = fManger;
    

    //......... suppressed code
    
    
    @SuppressLint("LongLogTag")
    @Override
    public void onBindViewHolder(AttractionsViewHolderPackageOffer holder, int position) 
        ItemPOA currentItem = mFavList.get(position);
        holder.Package_offer_title.setText(currentItem.get_Package_offer_title());
        
        holder.Card.setOnClickListener(v -> 
            DialogPOA dialog = new DialogPOA();
            dialog.show(fragmentMgr, "item");
            Bundle bundle1 = new Bundle();

            bundle1.putString("title_po", currentItem.get_Package_offer_title());
            bundle1.putString("description_po", currentItem.get_Package_offer_description());
            bundle1.putString("cost_po", currentItem.get_Package_offer_cost());
            dialog.setArguments(bundle1);
        );
        holder.getAdapterPosition();
    

    //......... suppressed code


【讨论】:

我更新了问题,你能看出Adapter和有什么区别吗?我只是不明白为什么我重复同样的事情,但它不起作用 我看不出两者之间的区别 .. 但选角不太对 .. 对话框是否相同? 不,dialog 其他,奇怪的是它不适用于此适配器

以上是关于DialogFragment 调用失败的主要内容,如果未能解决你的问题,请参考以下文章

DialogFragment: DialogFragment的一些理解

如何从Android中没有活动和片段的函数调用DialogFragment?

Android DialogFragment vs Dialog

将正/负按钮添加到 DialogFragment 的 Dialog

详细解读DialogFragment

Android为啥推荐用DialogFragment创建Dialog?