Reputation: 19
How can I add AdMob ads in a list view?
I just add MyAdapter
class and MyViewHolder class but I get an error.
Here is my code:
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
/// LIST ADS
private static final int MENU_ITEM_VIEW_TYP = 0;
private static final int AD_VIEW_TYPE = 1;
/// LIST ADS
Context c;
ArrayList<Article> articles;
public MyAdapter(Context c, ArrayList<Article> articles) {
this.c = c;
this.articles = articles;
}
public class NativeExpressAdsViewHoolder extends MyViewHolder {
NativeExpressAdsViewHoolder(View view){
super(view);
}
}
@Override
public int getItemCount() {
return articles.size();
}
@Override
public long getItemId(int position) {
return (position % 8 == 0) ? AD_VIEW_TYPE: position;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case AD_VIEW_TYPE:
View nativ = LayoutInflater.from(c).inflate(R.layout.native_expres_continer, parent, false);
return new MyViewHolder(nativ);
case MENU_ITEM_VIEW_TYP:
default:
View v = LayoutInflater.from(c).inflate(R.layout.model, parent, false);
return new MyViewHolder(v);
}
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Article article=articles.get(position);
NativeExpressAdsViewHoolder nativeExpressHolder = (NativeExpressAdsViewHoolder)holder;
NativeExpressAdView adsView = (NativeExpressAdView)articles.get(position);
Article adview=articles.get(position);
String title=article.getTitle();
String desc=article.getDescription();
String date=article.getDate();
/// String imageUrl=article.getImageUrl();
holder.titleTxt.setText(title);
holder.desctxt.setText(desc);
holder.dateTxt.setText(date);
// PicassoClient.downloadImage(c,imageUrl,holder.img);
}
}
Myviewholder class
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView titleTxt,desctxt,dateTxt,adview;
ImageView img;
public MyViewHolder(View itemView) {
super(itemView);
titleTxt= (TextView) itemView.findViewById(R.id.titleTxt);
desctxt= (TextView) itemView.findViewById(R.id.descTxt);
dateTxt= (TextView) itemView.findViewById(R.id.dateTxt);
// img= (ImageView) itemView.findViewById(R.id.articleImage);
}
}
Upvotes: 2
Views: 48
Reputation: 623
Without knowing the exact error you get I think the code might be problematic because of how you integrate the ads.
First you will never actually show all the articles actually in the list because you just say for every 8th article it should display an ad instead but the original 8th article in the list won't be shown.
Now I think where your example crashes is in onBindViewHolder
at the 8th element when you actually try to access titleTxt
, desctxt
or dateTxt
on it. The ViewHolder you inflated is a NativeExpressAdsViewHoolder
(because it's also of type RecyclerView.ViewHolder
<- btw you can leave that whole check. The holder
of onBindViewHolder
will always be a ViewHolder
) so it won't have those fields and the program will crash.
In order for this to work you will need to have a representation for the ads available in the backing collection you supply to the Adapter.
So instead of giving your Adapter a list of articles I would introduce an interface like this:
interface ListElement {
ElementType getType();
enum ElementType {
ARTICLE,
AD
}
}
Of course now your Article
class will need to implement this interface and always statically return ElementType.ARTICLE
in the getType
method and you need an empty class Ad
that also implements the interface and always returns ElementType.AD
in its getType
method.
Now I assume you load your articles somewhere from the web and then pass them to the Adapter? So now before passing them to the adapter you insert the Ad
placeholder classes. So whereever you instanciate your Adapter do something like this:
private MyAdapter createAdapter(List<Article> articlesLoadedFromWeb) {
final List<ListElement> articlesAndAds = new ArrayList<>();
for (int i = 0; i < articlesLoadedFromWeb.size(); i++) {
if (i % 8 == 0) {
articlesAndAds.add(new Ad());
} else {
articlesAndAds.add(articlesLoadedFromWeb(i));
}
}
return new MyAdapter(getContext(), articlesAndAds);
}
And then your Adapter could look like this:
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
final Context c;
final List<ListElement> articlesAndAds;
public MyAdapter(Context c, List<ListElement> articlesAndAds) {
this.c = c;
this.articlesAndAds = articlesAndAds;
}
public class NativeExpressAdsViewHolder extends MyViewHolder {
NativeExpressAdsViewHolder(View view){
super(view);
}
}
@Override
public int getItemCount() {
return articlesAndAds.size();
}
@Override
public long getItemId(int position) {
return articlesAndAds.get(position).getType().ordinal();
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case ListElement.ElementType.AD.ordinal():
View nativ = LayoutInflater.from(c).inflate(R.layout.native_express_container, parent, false);
return new MyViewHolder(nativ);
case ListElement.ElementType.ARTICLE.ordinal():
default:
View v = LayoutInflater.from(c).inflate(R.layout.model, parent, false);
return new MyViewHolder(v);
}
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
if (articlesAndAds.get(position).getType() == ListElement.ElementType.ARTICLE) {
final Article article = (Article) articles.get(position);
String title = article.getTitle();
String desc = article.getDescription();
String date = article.getDate();
/// String imageUrl = article.getImageUrl();
holder.titleTxt.setText(title);
holder.desctxt.setText(desc);
holder.dateTxt.setText(date);
// PicassoClient.downloadImage(c, imageUrl, holder.img);
}
}
}
Upvotes: 1