Java 带有片段的多个viewholder recyclerview上的强制转换异常

Java 带有片段的多个viewholder recyclerview上的强制转换异常,java,android,android-fragments,android-recyclerview,Java,Android,Android Fragments,Android Recyclerview,我正在尝试在我的应用程序中实现。它在recyclerview Adview和MenuItem中有两个视图持有者。如果它在一个活动中实现,那么它工作得非常好。但在我的例子中,我使用了一个片段作为底部导航条。它在第一次通过底部栏打开片段时起作用,但在那之后,它给出了强制转换异常 java.lang.ClassCastException: com.google.android.gms.ads.AdView cannot be cast to com.neupanedinesh.models.MenuI

我正在尝试在我的应用程序中实现。它在recyclerview Adview和MenuItem中有两个视图持有者。如果它在一个活动中实现,那么它工作得非常好。但在我的例子中,我使用了一个片段作为底部导航条。它在第一次通过底部栏打开片段时起作用,但在那之后,它给出了强制转换异常

java.lang.ClassCastException: com.google.android.gms.ads.AdView cannot be cast to com.neupanedinesh.models.MenuItem
        at com.neupanedinesh.adapters.RecyclerViewAdapter.onBindViewHolder
我已经将片段的onResume、onPause和onDestroy的访问类型从protected更改为public

 @Override
    public void onResume() {
        for (Object item : recyclerViewItems) {
            if (item instanceof AdView) {
                AdView adView = (AdView) item;
                adView.resume();
            }
        }
        super.onResume();
    }

    @Override
    public void onPause() {
        for (Object item : recyclerViewItems) {
            if (item instanceof AdView) {
                AdView adView = (AdView) item;
                adView.pause();
            }
        }
        super.onPause();
    }

    @Override
    public void onDestroy() {
        for (Object item : recyclerViewItems) {
            if (item instanceof AdView) {
                AdView adView = (AdView) item;
                adView.destroy();
            }
        }
        super.onDestroy();
    }
这是我的RecyclerView适配器:

package com.neupanedinesh.adapters;

import android.content.Context;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.google.android.gms.ads.AdView;
import com.neupanedinesh.coolcaptions.MenuItemFragment;
import com.neupanedinesh.coolcaptions.R;
import com.neupanedinesh.models.MenuItem;

import java.util.List;

/**
 * The {@link RecyclerViewAdapter} class.
 * <p>The adapter provides access to the items in the {@link MenuItemViewHolder}
 * or the {@link AdViewHolder}.</p>
 */
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    // A menu item view type.
    private static final int MENU_ITEM_VIEW_TYPE = 0;

    // The banner ad view type.
    private static final int BANNER_AD_VIEW_TYPE = 1;

    // An Activity's Context.
    private final Context context;

    // The list of banner ads and menu items.
    private final List<Object> recyclerViewItems;

    /**
     * For this example app, the recyclerViewItems list contains only
     * {@link MenuItem} and {@link AdView} types.
     */
    public RecyclerViewAdapter(Context context, List<Object> recyclerViewItems) {
        this.context = context;
        this.recyclerViewItems = recyclerViewItems;
    }

    /**
     * The {@link MenuItemViewHolder} class.
     * Provides a reference to each view in the menu item view.
     */
    public class MenuItemViewHolder extends RecyclerView.ViewHolder {
        private TextView menuItemName;

        MenuItemViewHolder(View view) {
            super(view);
            menuItemName = view.findViewById(R.id.menu_item_name);
        }
    }

    /**
     * The {@link AdViewHolder} class.
     */
    public class AdViewHolder extends RecyclerView.ViewHolder {

        AdViewHolder(View view) {
            super(view);
        }
    }

    @Override
    public int getItemCount() {
        return recyclerViewItems.size();
    }

    /**
     * Determines the view type for the given position.
     */
    @Override
    public int getItemViewType(int position) {
        return (position % MenuItemFragment.ITEMS_PER_AD == 0) ? BANNER_AD_VIEW_TYPE
                : MENU_ITEM_VIEW_TYPE;
    }

    /**
     * Creates a new view for a menu item view or a banner ad view
     * based on the viewType. This method is invoked by the layout manager.
     */
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        switch (viewType) {
            case MENU_ITEM_VIEW_TYPE:
                View menuItemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(
                        R.layout.menu_item_container, viewGroup, false);
                return new MenuItemViewHolder(menuItemLayoutView);
            case BANNER_AD_VIEW_TYPE:
                // fall through
            default:
                View bannerLayoutView = LayoutInflater.from(
                        viewGroup.getContext()).inflate(R.layout.banner_ad_container,
                        viewGroup, false);
                return new AdViewHolder(bannerLayoutView);
        }
    }

    /**
     * Replaces the content in the views that make up the menu item view and the
     * banner ad view. This method is invoked by the layout manager.
     */
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        int viewType = getItemViewType(position);
        switch (viewType) {
            case MENU_ITEM_VIEW_TYPE:
                MenuItemViewHolder menuItemHolder = (MenuItemViewHolder) holder;
                MenuItem menuItem = (MenuItem) recyclerViewItems.get(position);
                menuItemHolder.menuItemName.setText(menuItem.getName());
                break;
            case BANNER_AD_VIEW_TYPE:
                // fall through
            default:
                AdViewHolder bannerHolder = (AdViewHolder) holder;
                AdView adView = (AdView) recyclerViewItems.get(position);
                ViewGroup adCardView = (ViewGroup) bannerHolder.itemView;
                // The AdViewHolder recycled by the RecyclerView may be a different
                // instance than the one used previously for this position. Clear the
                // AdViewHolder of any subviews in case it has a different
                // AdView associated with it, and make sure the AdView for this position doesn't
                // already have a parent of a different recycled AdViewHolder.
                if (adCardView.getChildCount() > 0) {
                    adCardView.removeAllViews();
                }
                if (adView.getParent() != null) {
                    ((ViewGroup) adView.getParent()).removeView(adView);
                }

                // Add the banner ad to the ad view.
                adCardView.addView(adView);

        }
    }

}
package com.neupanedinesh.adapters;
导入android.content.Context;
导入androidx.recyclerview.widget.recyclerview;
导入android.view.LayoutInflater;
导入android.view.view;
导入android.view.ViewGroup;
导入android.widget.TextView;
导入com.google.android.gms.ads.AdView;
导入com.neupanedinesh.coolcaptions.MenuItemFragment;
导入com.neupanedinesh.coolcaptions.R;
导入com.neupanedinesh.models.MenuItem;
导入java.util.List;
/**
*{@link recycleServiceAdapter}类。
*适配器提供对{@link MenuItemViewHolder}中项目的访问
*或{@link AdViewHolder}

*/ 公共类RecycleServiceAdapter扩展了RecyclerView.Adapter{ //菜单项视图类型。 私有静态最终整数菜单\项\视图\类型=0; //横幅广告视图类型。 私有静态最终整幅广告视图类型=1; //活动的上下文。 私人最终语境; //横幅广告和菜单项的列表。 私人最终列表回收服务项目; /** *对于此示例应用程序,RecycleServiceItems列表仅包含 *{@link MenuItem}和{@link AdView}类型。 */ 公共RecycleServiceAdapter(上下文上下文、列表RecycleServiceItems){ this.context=上下文; this.RecycleServiceItems=RecycleServiceItems; } /** *{@link MenuItemViewHolder}类。 *提供对菜单项视图中每个视图的引用。 */ 公共类MenuItemViewHolder扩展了RecyclerView.ViewHolder{ 私有文本视图菜单项名称; MenuItemViewHolder(视图){ 超级(视图); menuItemName=view.findViewById(R.id.menu\u item\u name); } } /** *{@link AdViewHolder}类。 */ 公共类AdViewHolder扩展了RecyclerView.ViewHolder{ AdvieWolder(视图){ 超级(视图); } } @凌驾 public int getItemCount(){ 返回RecycleServiceItems.size(); } /** *确定给定位置的视图类型。 */ @凌驾 public int getItemViewType(int位置){ 返回(位置%MenuItemFragment.ITEMS\u PER\u AD==0)?横幅\u广告\u视图\u类型 :菜单项\视图\类型; } /** *为菜单项视图或横幅广告视图创建新视图 *基于视图类型。此方法由布局管理器调用。 */ @凌驾 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup ViewGroup,int viewType){ 开关(视图类型){ 案例菜单\项目\视图\类型: View menuItemLayoutView=LayoutFlater.from(viewGroup.getContext())。充气( R.layout.menu_项_容器,视图组,false); 返回新的MenuItemViewHolder(menuItemLayoutView); 案例标题\广告\视图\类型: //失败 违约: 视图bannerLayoutView=LayoutFlater.from( viewGroup.getContext())。充气(R.layout.banner\u广告容器, 视图组,false); 返回新的AdViewHolder(bannerLayoutView); } } /** *替换组成菜单项视图和 *横幅广告视图。此方法由布局管理器调用。 */ @凌驾 BindViewHolder上的公共无效(RecyclerView.ViewHolder,int位置){ int viewType=getItemViewType(位置); 开关(视图类型){ 案例菜单\项目\视图\类型: MenuItemViewHolder menuItemHolder=(MenuItemViewHolder)holder; MenuItem MenuItem=(MenuItem)recycleServiceItems.get(位置); menuItemHolder.menuItemName.setText(menuItem.getName()); 打破 案例标题\广告\视图\类型: //失败 违约: AdViewHolder横幅持有人=(AdViewHolder)持有人; AdView AdView=(AdView)recycleServiceItems.get(position); ViewGroup adCardView=(ViewGroup)bannerHolder.itemView; //由RecyclerView回收的AdViewHolder可能是另一个版本 //实例,而不是以前用于此位置的实例。清除 //任何子视图的AdViewHolder,以防其具有不同的 //与之关联的AdView,并确保此位置的AdView不存在 //已经有一个不同回收AdViewHolder的父级。 如果(adCardView.getChildCount()>0){ adCardView.RemoveAllView(); } if(adView.getParent()!=null){ ((ViewGroup)adView.getParent()).removeView(adView); } //将横幅广告添加到广告视图。 adcardwiew.addView(adView); } } }
这是我的片段类:

package com.neupanedinesh.coolcaptions;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdSize;
import com.google.android.gms.ads.AdView;

import java.util.ArrayList;
import java.util.List;

import com.neupanedinesh.adapters.RecyclerViewAdapter;
import com.neupanedinesh.models.MenuItem;


/**
 * A simple {@link Fragment} subclass.
 */
public class MenuItemFragment extends Fragment {

    // A banner ad is placed in every 8th position in the RecyclerView.
    public static final int ITEMS_PER_AD = 8;

    private static final String AD_UNIT_ID = "ca-app-pub-3940256099942544/4177191030";

    // The RecyclerView that holds and displays banner ads and menu items.
    private RecyclerView recyclerView;

    // List of banner ads and MenuItems that populate the RecyclerView.
    private List<Object> recyclerViewItems = new ArrayList<>();


    public MenuItemFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_menu_item, container, false);
        recyclerView = view.findViewById(R.id.recycler_view);

        // Use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView.
        recyclerView.setHasFixedSize(true);

        // Specify a linear layout manager.
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(layoutManager);

        // Update the RecyclerView item's list with menu items and banner ads.
        addMenuItemsFromJson();
        addBannerAds();
        loadBannerAds();

        // Specify an adapter.
        RecyclerView.Adapter<RecyclerView.ViewHolder> adapter = new RecyclerViewAdapter(getActivity(),
                recyclerViewItems);
        recyclerView.setAdapter(adapter);



        return view;
    }

    @Override
    public void onResume() {
        for (Object item : recyclerViewItems) {
            if (item instanceof AdView) {
                AdView adView = (AdView) item;
                adView.resume();
            }
        }
        super.onResume();
    }

    @Override
    public void onPause() {
        for (Object item : recyclerViewItems) {
            if (item instanceof AdView) {
                AdView adView = (AdView) item;
                adView.pause();
            }
        }
        super.onPause();
    }

    @Override
    public void onDestroy() {
        for (Object item : recyclerViewItems) {
            if (item instanceof AdView) {
                AdView adView = (AdView) item;
                adView.destroy();
            }
        }
        super.onDestroy();
    }


    /**
     * Adds banner ads to the items list.
     */
    private void addBannerAds() {
        // Loop through the items array and place a new banner ad in every ith position in
        // the items List.
        for (int i = 0; i <= recyclerViewItems.size(); i += ITEMS_PER_AD) {
            final AdView adView = new AdView(getActivity());
            adView.setAdSize(AdSize.BANNER);
            adView.setAdUnitId(AD_UNIT_ID);
            recyclerViewItems.add(i, adView);
        }
    }

    /**
     * Sets up and loads the banner ads.
     */
    private void loadBannerAds() {
        // Load the first banner ad in the items list (subsequent ads will be loaded automatically
        // in sequence).
        loadBannerAd(0);
    }

    /**
     * Loads the banner ads in the items list.
     */
    private void loadBannerAd(final int index) {

        if (index >= recyclerViewItems.size()) {
            return;
        }

        Object item = recyclerViewItems.get(index);
        if (!(item instanceof AdView)) {
            throw new ClassCastException("Expected item at index " + index + " to be a banner ad"
                    + " ad.");
        }

        final AdView adView = (AdView) item;

        // Set an AdListener on the AdView to wait for the previous banner ad
        // to finish loading before loading the next ad in the items list.
        adView.setAdListener(new AdListener() {
            @Override
            public void onAdLoaded() {
                super.onAdLoaded();
                // The previous banner ad loaded successfully, call this method again to
                // load the next ad in the items list.
                loadBannerAd(index + ITEMS_PER_AD);
            }

            @Override
            public void onAdFailedToLoad(int errorCode) {
                // The previous banner ad failed to load. Call this method again to load
                // the next ad in the items list.
               /* Log.e("MainActivity", "The previous banner ad failed to load. Attempting to"
                        + " load the next banner ad in the items list.");*/
                loadBannerAd(index + ITEMS_PER_AD);
            }
        });

        // Load the banner ad.
        adView.loadAd(new AdRequest.Builder().build());
    }


    private void addMenuItemsFromJson() {
        String menuItemName="item";
        MenuItem menuItem = new MenuItem(menuItemName);
        recyclerViewItems.add(menuItem);
    }


}
package com.neupanedinesh.coolcaptions;
导入android.os.Bundle;
导入androidx.fragment.app.fragment;
导入androidx.recyclerview.widget.LinearLayoutManager;
导入androidx.recyclerview.widget.recyclerview;
导入android.view.LayoutInflater;
导入android.view.view;
导入android.view.ViewGroup;
导入com.google.android.gms.ads.AdListener;
导入com.google.android.gms.ads.AdRequest;
导入com.google.android.gms.ads.AdSize;
导入com.google.android.gms.ads.AdView;
导入java.util.ArrayList;
我
@Override
public int getItemViewType(int position) {
    return (position % MenuItemFragment.ITEMS_PER_AD == 0) 
          ? BANNER_AD_VIEW_TYPE
          : MENU_ITEM_VIEW_TYPE;
}
Object item = recyclerViewItems.get(position);
if (item instanceOf AdView) {
    AdView adView = (AdView) recyclerViewItems.get(position);
} else if (item instanceOf MenuItem) {
    MenuItem menuItem = (MenuItem) recyclerViewItems.get(position);
}
@Override
public int getItemViewType(int position) {
    return recyclerViewItems.get(position) instanceOf AdView 
          ? BANNER_AD_VIEW_TYPE
          : MENU_ITEM_VIEW_TYPE;
}