我试图在RecyclerView中添加原生广告。我已经看过谷歌样本中提供的示例。该示例来自已填充的列表,然后向其添加广告原生广告。就我而言,我在我的适配器中使用onLoadMore为每个API调用加载了10个项目到RecyclerView。我希望我的广告在列表中的每个第8个位置展示。
根据谷歌示例here,它会检查列表中的每个第8,16,24位置。但是,当我最初在第一次迭代中添加广告时,项目总数变为12(10个列表项+第0个和第8个位置的2个广告)。在第二次迭代中,项目总数变为24(20个列表项+第0,第8,第12和第20位的4个广告)。在适配器中,它检查adview的第8个,第16个,第24个...位置。然后我得到了类强制转换异常,因为适配器正在第16个位置查看adview,但它实际上是菜单项。 我究竟做错了什么?帮我。下面是我的片段和适配器类。
适配器类:
public class NewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int REQUEST_FOR_ACTIVITY_CODE = 110;
boolean isBookmarked;
public static int lastAdPosition = 0;
public static class UserViewHolder extends RecyclerView.ViewHolder {
ImageView thumbnail;
CustomFontTextView share, bookmark, shortbyte;
TextView title;
LinearLayout linearLayout;
public UserViewHolder(View itemView) {
super(itemView);
this.linearLayout = (LinearLayout) itemView.findViewById(R.id.card_view_root_layout);
this.thumbnail = (ImageView) itemView.findViewById(R.id.activity_post_thumbnail);
this.share = (CustomFontTextView) itemView.findViewById(R.id.share);
this.bookmark = (CustomFontTextView) itemView.findViewById(R.id.bookmark);
this.shortbyte = (CustomFontTextView) itemView.findViewById(R.id.shortbyte);
this.title = (TextView) itemView.findViewById(R.id.post_title);
}
}
public static class LoadingViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public LoadingViewHolder(View itemView) {
super(itemView);
progressBar = (ProgressBar) itemView.findViewById(R.id.progressBar1);
}
}
public class AdViewHolder extends RecyclerView.ViewHolder {
AdViewHolder(View view) {
super(view);
}
}
private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1;
private final int VIEW_TYPE_AD = 2;
List<Integer> adPositionList = new ArrayList<>();
private OnLoadMoreListener mOnLoadMoreListener;
private boolean isLoading;
private int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
private List<Object> adapterPostList;
private Typeface customFont;
DataStorage sharedPreference;
Context context;
Activity activity;
RecyclerView recyclerView;
private static boolean isLoadingVisible;
private boolean isBookmarkCalledFromMainActivity;
private CoordinatorLayout frameLayout;
private Typeface custom_font, custom_font2;
private int screenWidth;
private LinearLayout linearLayout;
private boolean isFromSearchActivity;
public NewAdapter(List<Object> postListFromMainActivity, Context context, Activity activity,
RecyclerView recyclerView, boolean isBookmarkCalledFromMainActivity, CoordinatorLayout frameLayout,
boolean isFromSearchActivity, LinearLayout linearLayout) {
this.frameLayout = frameLayout;
this.linearLayout = linearLayout;
this.isBookmarkCalledFromMainActivity = isBookmarkCalledFromMainActivity;
this.isFromSearchActivity = isFromSearchActivity;
this.recyclerView = recyclerView;
this.activity = activity;
this.context = context;
customFont = Typeface.createFromAsset(context.getAssets(), "fonts/RobotoCondensed-Bold.ttf");
sharedPreference = new DataStorage();
adapterPostList = new ArrayList<>();
adapterPostList = postListFromMainActivity;
custom_font = Typeface.createFromAsset(context.getAssets(), "fonts/RobotoCondensed-Light_0.ttf");
custom_font2 = Typeface.createFromAsset(context.getAssets(), "fonts/RobotoCondensed-Regular_0.ttf");
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
if (mOnLoadMoreListener != null) {
mOnLoadMoreListener.onLoadMore();
}
isLoading = true;
}
}
});
}
public void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
this.mOnLoadMoreListener = mOnLoadMoreListener;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_ITEM) {
View view = LayoutInflater.from(context).inflate(R.layout.item_post_layout, parent, false);
return new UserViewHolder(view);
} else if (viewType == VIEW_TYPE_LOADING) {
View view = LayoutInflater.from(context).inflate(R.layout.layout_loading_item, parent, false);
return new LoadingViewHolder(view);
} else if (viewType == VIEW_TYPE_AD) {
View view = LayoutInflater.from(context).inflate(R.layout.native_express_ad_container, parent, false);
return new AdViewHolder(view);
}
return null;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof UserViewHolder) {
#some code
} else if (holder instanceof LoadingViewHolder) {
if (!isLoadingVisible) {
isLoadingVisible = true;
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true);
}
} else if (holder instanceof AdViewHolder) {
AdViewHolder nativeExpressHolder = (AdViewHolder) holder;
NativeExpressAdView adView = (NativeExpressAdView) adapterPostList.get(position);
ViewGroup adCardView = (ViewGroup) nativeExpressHolder.itemView;
if (adCardView.getChildCount() > 0) {
adCardView.removeAllViews();
}
if (adView.getParent() != null) {
((ViewGroup) adView.getParent()).removeView(adView);
}
// Add the Native Express ad to the native express ad view.
adCardView.addView(adView);
}
}
@Override
public int getItemCount() {
return adapterPostList == null ? 0 : adapterPostList.size();
}
public void setLoaded() {
isLoading = false;
}
@Override
public int getItemViewType(int position) {
if (adapterPostList.get(position) == null) {
return VIEW_TYPE_LOADING;
} else if ( position % HomeFragment.ITEMS_PER_AD == 0) {
return VIEW_TYPE_AD;
} else {
return VIEW_TYPE_ITEM;
}
}
public void add(Posts product) {
adapterPostList.add(product);
notifyDataSetChanged();
}
public void remove(Posts product) {
adapterPostList.remove(product);
notifyDataSetChanged();
}
public void clear() {
try {
((AppCompatActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
adapterPostList.clear();
notifyDataSetChanged();
}
});
} catch (WindowManager.BadTokenException e) {
} catch (Exception e) {
}
}
public void addAll(List<Object> list) {
adapterPostList.addAll(list);
notifyDataSetChanged();
}
片段类:
public class HomeFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private RecyclerView postsRecyclerView;
private RecyclerView.LayoutManager layoutManager;
private List<Object> postsLists;
private NewAdapter postsListAdapter;
private int pageNo = 1;
private boolean responseCalled = false;
private Activity activity;
private ProgressBar bar;
private CoordinatorLayout coordinatorLayout;
private String url;
boolean doubleBackToExitPressedOnce = false;
private Context context;
private SwipeRefreshLayout mWaveSwipeRefreshLayout;
private boolean isRefreshing = false, isPostsAdapterClearedOnce = false;
private CardView refresh;
private TextView noInternet, cardText;
public static boolean isHomeFragment;
private DataStorage sharedPreference;
private static final String AD_UNIT_ID = "ca-app-pub-3940256099942544/1072772517";
public static final int ITEMS_PER_AD = 8;
// The Native Express ad height.
private static final int NATIVE_EXPRESS_AD_HEIGHT = 150;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
setHasOptionsMenu(true);
isHomeFragment = true;
sharedPreference = new DataStorage();
coordinatorLayout = (CoordinatorLayout) rootView.findViewById(R.id.frame_container);
postsRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
url = ServiceURLManager.getInstance().getPostsUrl(pageNo);
postsLists = new ArrayList<>();
context = getActivity();
activity = getActivity();
bar = (ProgressBar) rootView.findViewById(R.id.progressBar);
bar.setIndeterminate(true);
bar.setVisibility(View.VISIBLE);
refresh = (CardView) rootView.findViewById(R.id.refresh);
cardText = (TextView) rootView.findViewById(R.id.cardText);
cardText.setText("No Connection! Retry.");
noInternet = (TextView) rootView.findViewById(R.id.noInternetConnection);
refresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
refresh();
}
});
String myUrl = ServiceURLManager.getInstance().getPostsUrl(1);
if (!Utils.getInstance().isNetworkAvailable(context)) {
refresh.setVisibility(View.VISIBLE);
noInternet.setVisibility(View.INVISIBLE);
} else if (!SingleArticleActivity.iscalledfromSingleArticleActivity) {
VolleySingleton.getInstance(getContext()).getRequestQueue().getCache().remove(myUrl);
}
callMorePosts(url);
initializeAdapter();
initView(rootView);
return rootView;
}
public boolean checkFavoriteItem(Posts checkProduct) {
boolean check = false;
List<Posts> favorites = sharedPreference.getFavorites(context);
if (favorites != null) {
for (Posts product : favorites) {
if (product.getPostId().equals(checkProduct.getPostId())) {
check = true;
break;
}
}
}
return check;
}
public void refresh() {
if (Utils.getInstance().isNetworkAvailable(context)) {
bar.setVisibility(View.VISIBLE);
refresh.setVisibility(View.INVISIBLE);
noInternet.setVisibility(View.INVISIBLE);
callMorePosts(url);
initializeAdapter();
}
}
private void initView(View view) {
mWaveSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.main_swipe);
mWaveSwipeRefreshLayout.setColorSchemeColors(getResources().getColor(R.color.appcolor));
mWaveSwipeRefreshLayout.setOnRefreshListener(this);
}
private void hideProgressBar() {
try {
((MainActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
if (bar != null) {
bar.setVisibility(View.GONE);
}
}
});
} catch (WindowManager.BadTokenException e) {
} catch (Exception e) {
}
}
private void initializeAdapter() {
postsRecyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(getActivity());
postsRecyclerView.setLayoutManager(layoutManager);
postsListAdapter = new NewAdapter(postsLists, getActivity(), activity, postsRecyclerView, true, coordinatorLayout, false, null);
AlphaInAnimationAdapter alphaAdapter = new AlphaInAnimationAdapter(postsListAdapter);
postsRecyclerView.setAdapter(new ScaleInAnimationAdapter(alphaAdapter));
postsListAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore() {
postsLists.add(null);
postsListAdapter.notifyItemInserted(postsLists.size() - 1);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
postsLists.remove(postsLists.size() - 1);
postsListAdapter.notifyItemRemoved(postsLists.size());
responseCalled = false;
url = ServiceURLManager.getInstance().getPostsUrl(pageNo);
callMorePosts(url);
}
}, 5000);
}
});
}
@Override
public void onResume() {
super.onResume();
if (postsListAdapter != null)
postsListAdapter.notifyDataSetChanged();
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
if (drawer.isDrawerOpen(Gravity.LEFT)) {
drawer.closeDrawer(Gravity.LEFT);
} else {
if (doubleBackToExitPressedOnce) {
getActivity().finish();
}
doubleBackToExitPressedOnce = true;
showSnackbar("Press again to exit");
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
return true;
}
}
return false;
}
});
}
public void showSnackbar(String message) {
Snackbar snackbar = Snackbar
.make(postsRecyclerView, message, Snackbar.LENGTH_LONG);
snackbar.show();
}
private void callMorePosts(String url) {
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
if (!responseCalled) {
Log.d("RECENT_RESPONSE", response.toString());
responseCalled = true;
try {
String status = response.getString("status");
if (status.equalsIgnoreCase("ok")) {
JSONArray jsonPostsArray = response.getJSONArray("posts");
isPostsAdapterClearedOnce = true;
int i;
if (jsonPostsArray.length() > 0) {
for (i = 0; i < jsonPostsArray.length(); i++) {
JSONObject jsonPostObject = jsonPostsArray.getJSONObject(i);
Posts postsItems = new Posts();
String thumbnailMedium = jsonPostObject.getString("thumbnail");
thumbnailMedium = thumbnailMedium.replace("-150x150", "");
postsItems.setThumbnail(thumbnailMedium);
postsItems.setPostId(jsonPostObject.getString("id"));
postsItems.setExcerpt(jsonPostObject.getString("excerpt"));
postsItems.setContent(jsonPostObject.getString("content"));
String newTitle = jsonPostObject.optString("title").replaceAll("̶\\d;", "\"");
newTitle = newTitle.replaceAll("’", "'");
newTitle = newTitle.replaceAll("‘", "'");
newTitle = newTitle.replaceAll("–", "-");
newTitle = newTitle.replaceAll("—", "-");
newTitle = newTitle.replaceAll("&", "&");
postsItems.setTitle(newTitle);
postsItems.setUrl(jsonPostObject.optString("url"));
postsItems.setDate(jsonPostObject.optString("date"));
postsItems.setPostCountTotal(jsonPostObject.optInt("count_total"));
postsItems.setPageCount(jsonPostObject.optInt("pages"));
JSONObject jsonAuthorObject = jsonPostObject.getJSONObject("author");
Author author = new Author();
author.setFirst_name(jsonAuthorObject.getString("first_name"));
author.setLast_name(jsonAuthorObject.getString("last_name"));
author.setId(jsonAuthorObject.optInt("id"));
author.setDescription(jsonAuthorObject.getString("description"));
postsItems.setAuthor(author);
JSONArray jsonTagsArray = jsonPostObject.getJSONArray("tags");
List<Tags> tagsList = new ArrayList<Tags>();
for (int j = 0; j < jsonTagsArray.length(); j++) {
JSONObject jsonTagsObject = jsonTagsArray.getJSONObject(j);
Tags tagsItems = new Tags();
tagsItems.setId(jsonTagsObject.optInt("id"));
tagsItems.setTitle(jsonTagsObject.optString("title"));
tagsItems.setPost_count(jsonTagsObject.getInt("post_count"));
tagsList.add(tagsItems);
}
postsItems.setTags(tagsList);
postsItems.setSlug(jsonPostObject.optString("slug"));
if (isRefreshing && isPostsAdapterClearedOnce) {
postsListAdapter.clear();
isRefreshing = false;
isPostsAdapterClearedOnce = false;
}
postsLists.add(postsItems);
}
}
hideProgressBar();
pageNo = pageNo + 1;
addNativeExpressAds();
setUpAndLoadNativeExpressAds();
mWaveSwipeRefreshLayout.setRefreshing(false);
postsListAdapter.notifyDataSetChanged();
postsListAdapter.setLoaded();
} else {
}
} else {
Toast.makeText(getActivity(), "Server is down. Try after sometime.", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Log.e("POSTLISTADAPTER", "Error on :" + pageNo + " " + e.getMessage().toString());
}
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("RECENT_ERROR", "Error: " + error.getMessage());
hideProgressBar();
if (error != null && error.networkResponse != null && error.networkResponse.statusCode == HttpURLConnection.HTTP_NOT_FOUND) {
Toast.makeText(getActivity(), "Error fetching content", Toast.LENGTH_LONG).show();
}
}
}) {
@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
Cache.Entry cacheEntry = HttpHeaderParser.parseCacheHeaders(response);
if (cacheEntry == null) {
cacheEntry = new Cache.Entry();
}
long now = System.currentTimeMillis();
final long softExpire = now + AppConstants.cacheHitButRefreshed;
final long ttl = now + AppConstants.cacheExpired;
cacheEntry.data = response.data;
cacheEntry.softTtl = softExpire;
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 JSONObject(jsonString), cacheEntry);
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException e) {
return Response.error(new ParseError(e));
}
}
@Override
protected void deliverResponse(JSONObject response) {
super.deliverResponse(response);
}
@Override
public void deliverError(VolleyError error) {
super.deliverError(error);
}
@Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
return super.parseNetworkError(volleyError);
}
};
VolleySingleton.getInstance(getActivity()).addToRequestQueue(jsonObjReq);
}
@Override
public void onRefresh() {
if (Utils.getInstance().isNetworkAvailable(context)) {
refresh.setVisibility(View.INVISIBLE);
}
isRefreshing = true;
responseCalled = false;
pageNo = 1;
String url = ServiceURLManager.getInstance().getPostsUrl(pageNo);
callMorePosts(url);
}
private void addNativeExpressAds() {
for (int i = 0; i <= postsLists.size(); i += ITEMS_PER_AD) {
final NativeExpressAdView adView = new NativeExpressAdView(context);
postsLists.remove(i);
postsLists.add(i, adView);
}
}
private void setUpAndLoadNativeExpressAds() {
postsRecyclerView.post(new Runnable() {
@Override
public void run() {
final float scale = context.getResources().getDisplayMetrics().density;
CardView cardViewTemp = null;
for (int i = 0; i <= postsLists.size(); i += ITEMS_PER_AD) {
final NativeExpressAdView adView =
(NativeExpressAdView) postsLists.get(i);
final CardView cardView = (CardView) getActivity().findViewById(R.id.ad_card_view);
cardViewTemp = cardView;
if (cardView != null) {
final int adWidth = cardView.getWidth() - cardView.getPaddingLeft()
- cardView.getPaddingRight();
AdSize adSize = new AdSize((int) (adWidth / scale), NATIVE_EXPRESS_AD_HEIGHT);
adView.setAdSize(adSize);
adView.setAdUnitId(AD_UNIT_ID);
}
}
if (cardViewTemp != null)
loadNativeExpressAd(0);
}
});
}
private void loadNativeExpressAd(final int index) {
if (index >= postsLists.size()) {
return;
}
Object item = postsLists.get(index);
if (!(item instanceof NativeExpressAdView)) {
throw new ClassCastException("Expected item at index " + index + " to be a Native"
+ " Express ad.");
}
final NativeExpressAdView adView = (NativeExpressAdView) item;
adView.setAdListener(new AdListener() {
@Override
public void onAdLoaded() {
super.onAdLoaded();
loadNativeExpressAd(index + ITEMS_PER_AD);
}
@Override
public void onAdFailedToLoad(int errorCode) {
Log.e("MainActivity", "The previous Native Express ad failed to load. Attempting to"
+ " load the next Native Express ad in the items list.");
loadNativeExpressAd(index + ITEMS_PER_AD);
}
});
adView.loadAd(new AdRequest.Builder().build());
}
}