RecyclerView集成AdMob横幅广告时出现ClassCastException问题求助
你遇到的com.example.abcd.CategoryItem cannot be cast to com.google.android.ads.AdView异常,核心原因是RecyclerView的视图类型判断逻辑和列表中实际元素的类型不匹配,导致绑定视图时错误地将CategoryItem强转为AdView。下面一步步帮你修复:
1. 调整广告插入的时机
你当前在onCreate中先调用异步的parseJSON(),紧接着就执行addBannerAds()——但此时mCategoryList还是空的,只会在位置0插入一个广告。等后续JSON数据加载完成,大量CategoryItem被添加到列表后,你没有补插后续的广告,而getItemViewType里用position % ITEMS_PER_AD == 0的判断,会把第8、16等原本是CategoryItem的位置错误标记为广告视图类型,最终触发强转异常。
修复步骤:
- 在
onCreate中提前初始化适配器:// 替换原来的适配器创建代码 mCategoryAdapter = new CategoryAdapter(this, mCategoryList); mRecyclerView.setAdapter(mCategoryAdapter); - 把
addBannerAds()和loadBannerAds()移到parseJSON的onResponse方法末尾,等所有CategoryItem添加完成后再插入广告:// 在parseJSON的onResponse循环添加完CategoryItem后: for (int i = 0; i < sortedCategory.length(); i++) { JSONObject hit = sortedCategory.getJSONObject(i); String categoryItem=hit.getString("term"); mCategoryList.add(new CategoryItem(categoryItem)); } // 移到这里执行广告插入 addBannerAds(); loadBannerAds(); // 通知适配器数据更新 mCategoryAdapter.notifyDataSetChanged();
2. 修复视图类型判断逻辑
用位置取模的方式判断视图类型非常不可靠,一旦列表元素发生变化(比如插入广告、数据刷新),位置和元素类型的对应关系就会混乱。更稳妥的方式是直接根据当前元素的类型来判断视图类型:
修改CategoryAdapter中的getItemViewType方法:
@Override public int getItemViewType(int position) { // 直接判断当前位置的元素类型 return mCategoryList.get(position) instanceof AdView ? BANNER_AD_VIEW_TYPE : MENU_ITEM_VIEW_TYPE; }
这样就能确保每个位置的视图类型和实际元素完全匹配,从根源上避免强转错误。
3. 优化广告插入的循环逻辑
原来的addBannerAds()循环条件i<=mCategoryList.size()可能导致列表末尾出现多余广告,而且插入广告后没有考虑索引偏移(插入一个广告会让后续元素的索引+1),导致广告位置计算错误。调整后的代码:
private void addBannerAds(){ int adIndex = ITEMS_PER_AD; // 循环插入广告,每次插入后索引跳过广告本身 while (adIndex < mCategoryList.size()) { final AdView adView = new AdView (CategoryActivity.this); adView.setAdSize(AdSize.BANNER); adView.setAdUnitId(AD_UNIT_ID); mCategoryList.add(adIndex, adView); adIndex += ITEMS_PER_AD + 1; // +1是跳过刚插入的广告 } }
这样每8个CategoryItem后会插入一个广告,位置计算更准确。
做完以上调整后,你的RecyclerView就能正确区分CategoryItem和广告视图,不会再出现ClassCastException了。
内容的提问来源于stack exchange,提问作者Bhelasagar Meher

