I have an app that stores some data in room database. At first, my adapter was like that:
public class ViewCourseAdapter extends ListAdapter<Course, ViewCourseAdapter.ViewCourseHolder> {
private int previousPosition = 0;
public ViewCourseAdapter() {
super(DIFF_CALLBACK);
}
private static final DiffUtil.ItemCallback<Course> DIFF_CALLBACK = new DiffUtil.ItemCallback<Course>() {
#Override
public boolean areItemsTheSame(#NonNull Course oldItem, #NonNull Course newItem) {
return oldItem.getId() == newItem.getId();
}
#Override
public boolean areContentsTheSame(#NonNull Course oldItem, #NonNull Course newItem) {
return oldItem.getfName().equals(newItem.getfName());
}
};
#NonNull
#Override
public ViewCourseHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_courses_item, parent, false);
return new ViewCourseHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull ViewCourseHolder holder, int position) {
Course currentCourse = getItem(position);
String fullName = currentCourse.getfName() + " " + currentCourse.getlName();
SpannableString SfullName = new SpannableString(fullName);
SfullName.setSpan(new UnderlineSpan(), 0, fullName.length(), 0);
holder.text_view_firstName_1.setText(SfullName);
if (position > previousPosition) {
AnimationUtil.animate(holder, true);
} else {
AnimationUtil.animate(holder, false);
}
previousPosition = position;
}
class ViewCourseHolder extends RecyclerView.ViewHolder {
private TextView text_view_firstName_1;
ViewCourseHolder(#NonNull View itemView) {
super(itemView);
text_view_firstName_1 = itemView.findViewById(R.id.text_view_firstName_1);
}
}
#Override
public int getItemCount() {
return super.getItemCount();
}
And everything was working perfect. Now I want to show ads inside recyclerview, so I changed my adapter:
public class ViewCourseAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int COURSE_VIEW_TYPE = 0;
private static final int AD_VIEW_TYPE = 1;
private List<Course> data;
private List<Object> ad;
private Context context;
private LayoutInflater layoutInflater;
private int previousPosition = 0;
public ViewCourseAdapter(Context context, List<Object> ad) {
this.data = new ArrayList<>();
this.context = context;
this.layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.ad = ad;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType ) {
case COURSE_VIEW_TYPE:
View courseView = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_courses_item, parent, false);
return new ViewCourseViewHolder(courseView);
case AD_VIEW_TYPE:
default:
View adView = LayoutInflater.from(parent.getContext()).inflate(R.layout.native_ads, parent, false);
return new AdViewHolder(adView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType) {
case COURSE_VIEW_TYPE:
ViewCourseViewHolder holder1 = (ViewCourseViewHolder) holder;
Course currentCourse = (Course) data.get(position);
String fullName = currentCourse.getfName() + " " + currentCourse.getlName();
SpannableString SfullName = new SpannableString(fullName);
SfullName.setSpan(new UnderlineSpan(), 0, fullName.length(), 0);
holder1.text_view_firstName_1.setText(SfullName);
break;
case AD_VIEW_TYPE:
default:
AdViewHolder bannerHolder = (AdViewHolder) holder;
AdView adView = (AdView) ad.get(position);
ViewGroup adCardView = (ViewGroup) bannerHolder.itemView;
if (adCardView.getChildCount() > 0) {
adCardView.removeAllViews();
}
if (adView.getParent() != null) {
((ViewGroup) adView.getParent()).removeView(adView);
}
adCardView.addView(adView);
}
if (position > previousPosition) {
AnimationUtil.animate(holder, true);
} else {
AnimationUtil.animate(holder, false);
}
previousPosition = position;
}
class AdViewHolder extends RecyclerView.ViewHolder {
AdViewHolder(View view) {
super(view);
}
}
#Override
public int getItemViewType(int position) {
return (position % ViewCoursesActivity.ITEMS_PER_AD == 0) ? AD_VIEW_TYPE
: COURSE_VIEW_TYPE;
}
#Override
public int getItemCount() {
return data.size();
}
public void setData(List<Course> newData) {
if (data != null) {
CourseDiffCallback courseDiffCallback = new CourseDiffCallback(data, newData);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(courseDiffCallback);
data.clear();
data.addAll(newData);
diffResult.dispatchUpdatesTo(this);
} else {
data = newData;
}
}
public class ViewCourseViewHolder extends RecyclerView.ViewHolder {
private TextView text_view_firstName_1;
ViewCourseViewHolder(#NonNull View itemView) {
super(itemView);
text_view_firstName_1 = itemView.findViewById(R.id.text_view_firstName_1);
}
}
private class CourseDiffCallback extends DiffUtil.Callback {
private final List<Course> oldItem, newItem;
private CourseDiffCallback(List<Course> oldItem, List<Course> newItem) {
this.oldItem = oldItem;
this.newItem = newItem;
}
#Override
public int getOldListSize() {
return oldItem.size();
}
#Override
public int getNewListSize() {
return newItem.size();
}
#Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldItem.get(oldItemPosition).getId() == newItem.get(newItemPosition).getId();
}
#Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return oldItem.get(oldItemPosition).getfName().equals(newItem.get(newItemPosition).getfName());
}
}
And my activity is:
public class ViewCoursesActivity extends AppCompatActivity {
private CourseViewModel courseViewModel;
// 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/6300978111";
// 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> data = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_courses);
recyclerView = findViewById(R.id.recycler_view_3);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
addBannerAds();
loadBannerAds();
final ViewCourseAdapter adapter = new ViewCourseAdapter(this, data);
recyclerView.setAdapter(adapter);
courseViewModel = ViewModelProviders.of(this).get(CourseViewModel.class);
courseViewModel.setIdForCourse(0);
//courseViewModel.getCourseByStudentId().observe(this, adapter::submitList);
courseViewModel.getCourseByStudentId().observe(this, adapter::setData);
}
#Override
protected void onResume() {
for (Object item : data) {
if (item instanceof AdView) {
AdView adView = (AdView) item;
adView.resume();
}
}
super.onResume();
}
#Override
protected void onPause() {
for (Object item : data) {
if (item instanceof AdView) {
AdView adView = (AdView) item;
adView.pause();
}
}
super.onPause();
}
#Override
protected void onDestroy() {
for (Object item : data) {
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 <= data.size(); i += ITEMS_PER_AD) {
final AdView adView = new AdView(ViewCoursesActivity.this);
adView.setAdSize(AdSize.SMART_BANNER);
adView.setAdUnitId(AD_UNIT_ID);
data.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 >= data.size()) {
return;
}
Object item = data.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("ViewCoursesActivity", "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());
}
After that I have two problems:
1. At frist position it display an ad instead of first item from my database, and first item is nowhere. If I check my database first item is there, just not apear in recyclerview.
2. If I want to scroll items, the app crash, and the error is "java.lang.IndexOutOfBoundsException: Index: 8, Size: 1".
What am I doing wrong?
Please help me. Thank you!
Fundamentally, a RecyclerView is used to display a List to the user. Use this to guide your implementation.
Currently, you have two lists:
private List<Course> data;
private List<Object> ad;
You need to find a way to "collate" these down to a single list. Maybe something like this:
private static List<Object> collate(List<Course> data, List<Object> ads) {
List<Object> collated = new ArrayList<>();
while (data.size() > 0 || ads.size() > 0) {
for (int i = 0; i < ITEMS_PER_AD && data.size() > 0; ++i) {
collated.add(data.remove(0));
}
if (ads.size() > 0) {
collated.add(ads.remove(0));
}
}
return collated;
}
With that method defined, you can replace your existing constructor:
private List<Course> data;
private List<Object> ad;
// ...
public ViewCourseAdapter(Context context, List<Object> ad) {
this.data = new ArrayList<>();
this.ad = ad;
// ...
}
with this:
private List<Object> ad;
private List<Object> collated;
// ...
public ViewCourseAdapter(Context context, List<Object> ad) {
this.ad = ad;
this.collated = new ArrayList<>(ad);
// ...
}
And you can replace your existing setData() method:
public void setData(List<Course> newData) {
if (data != null) {
CourseDiffCallback courseDiffCallback = new CourseDiffCallback(data, newData);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(courseDiffCallback);
data.clear();
data.addAll(newData);
diffResult.dispatchUpdatesTo(this);
} else {
data = newData;
}
}
with this:
public void setData(List<Course> newData) {
if (data != null) {
List<Object> newCollated = collate(ad, newData);
// setup DiffUtil callback here...
this.collated = newCollated;
// dispatch DiffUtil result here...
}
}
Now you will have a single list that you can use in your adapter. Then you can change your adapter's methods to use that one list:
#Override
public int getItemCount() {
return collated.size();
}
#Override
public int getItemViewType(int position) {
return (collated.get(position) instanceof Course)
? COURSE_VIEW_TYPE
: AD_VIEW_TYPE;
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
if (holder.getItemViewType() == COURSE_VIEW_TYPE) {
bindCourseHolder((ViewCourseViewHolder) holder, position);
} else if (holder.getItemViewType() == AD_VIEW_TYPE) {
bindAdHolder((AdViewHolder) holder, position);
}
}
private void bindCourseHolder(ViewCourseViewHolder holder, int position) {
// ...
}
private void bindAdHolder(AdViewHolder holder, int position) {
// ...
}
All of these changes are based on the fundamental concept that you just have a single list, and that list holds (potentially) many different types of things.
Thank you #Ben P. for advice...I can't believe I didn't see this...so I modify collate() method like this:
while (data.size() > 0) {
collated.addAll(ad);
for (int i = 0; i < ITEMS_PER_AD && data.size() > 0; ++i) {
collated.add(data.remove(0));
}
}
ad.remove(0);
return collated;
It is there a better way to do this?
Related
What i am doing is, that i have a recyclerView which has it's adapter and from within adapter i am loading the nativeAds. But due to loading the ads within the recyclerView instead of preloading the ads my recyclerView is not scrolling smoothly.
And also i tried to load the native ad on different thread but that also was't helpful.
Any ideas how to load the native ad without sacrificing the performance??
public class GetInspiredAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public static int VIEW_TYPE_ADS = 0;
public static int VIEW_TYPE_NOTADS = 1;
// this shows that the ad is to be added after this many items.
public static int ADS_AFTER_HOW_MANY_ITEMS = 3;
private boolean isNetworkAvailable = false;
private Context context;
private ArrayList<Object> list;
private GetInspiredListener listener;
public GetInspiredAdapter(Context context, ArrayList<Object> list, GetInspiredListener listener) {
this.context = context;
this.list = list;
this.listener = listener;
}
private void addNativeToList() {
int i = ADS_AFTER_HOW_MANY_ITEMS;
while (i < list.size()) {
list.add(i, new UnifiedNativeAdView(context));
i += ADS_AFTER_HOW_MANY_ITEMS + 1;
}
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
if (viewType == VIEW_TYPE_ADS) {
View unifiedNativeLayoutView = LayoutInflater.from(context).inflate(R.layout.ad_unified, viewGroup, false);
unifiedNativeLayoutView.setTag(new Integer(GetInspiredAdapter.VIEW_TYPE_ADS));
return new UnifiedNativeAdViewHolder(unifiedNativeLayoutView);
} else {
View itemView = LayoutInflater.from(context).inflate(R.layout.image_item, viewGroup, false);
itemView.setTag(new Integer(GetInspiredAdapter.VIEW_TYPE_NOTADS));
return new GetInspiredViewHolder(itemView);
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
if (viewType == VIEW_TYPE_ADS) {
if (!isNetworkAvailable) {
list.remove(position);
notifyDataSetChanged();
return;
}
AdLoader.Builder builder = new AdLoader.Builder(context, Constants.INSPIRED_MOB)
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
populateNativeAdView(unifiedNativeAd, (UnifiedNativeAdViewHolder) holder);
}
}).withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int i) {
super.onAdFailedToLoad(i);
}
});
builder.build().loadAd(new AdRequest.Builder().build());
} else if (viewType == VIEW_TYPE_NOTADS) {
LoadImage((InspiredObject) list.get(getItemIndex(position)), (GetInspiredViewHolder) holder);
}
}
private void LoadImage(InspiredObject obj, GetInspiredViewHolder viewHolder) {
//Url link to images
String url = "http://aim-itech.com/mandala/image/";
String string = url + obj.low;
Glide.with(context).load(string).override(Constants.SAMPLE_SIZE_MEDIUM).into(viewHolder.imageView);
Log.e("TAG", string);
}
private void populateNativeAdView(UnifiedNativeAd nativeAd, UnifiedNativeAdViewHolder holder) {
if (nativeAd == null) {
holder.getAdView().setVisibility(View.INVISIBLE);
holder.textLoading.setVisibility(View.VISIBLE);
return;
}
holder.textLoading.setVisibility(View.GONE);
UnifiedNativeAdView adView = holder.getAdView();
adView.setVisibility(View.VISIBLE);
((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
((TextView) adView.getBodyView()).setText(nativeAd.getBody());
((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
NativeAd.Image icon = nativeAd.getIcon();
if (icon == null) {
adView.getIconView().setVisibility(View.INVISIBLE);
} else {
((ImageView) adView.getIconView()).setImageDrawable(icon.getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (nativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
} else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
}
if (nativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
} else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView) adView.getStoreView()).setText(nativeAd.getStore());
}
if (nativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
} else {
((RatingBar) adView.getStarRatingView())
.setRating(nativeAd.getStarRating().floatValue());
adView.getStarRatingView().setVisibility(View.VISIBLE);
}
if (nativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
} else {
((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
adView.getAdvertiserView().setVisibility(View.VISIBLE);
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeAd);
}
public int getItemIndex(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
Object recyclerViewItem = list.get(getItemIndex(position));
if (recyclerViewItem instanceof UnifiedNativeAd) {
return VIEW_TYPE_ADS;
} else if (recyclerViewItem instanceof UnifiedNativeAdView) {
return VIEW_TYPE_ADS;
}
return VIEW_TYPE_NOTADS;
}
public boolean isNetworkAvailable() {
return isNetworkAvailable;
}
public void setNetworkAvailable(boolean networkAvailable) {
isNetworkAvailable = networkAvailable;
if (isNetworkAvailable) {
addNativeToList();
}
}
#Override
public int getItemCount() {
return list.size();
}
public class GetInspiredViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public GetInspiredViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.imageProf);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
InspiredObject inspiredObject = (InspiredObject) list.get(getAdapterPosition());
Intent i = new Intent(context, InspiredActivity.class);
i.putExtra("image", inspiredObject.high);
listener.onClick(i);
}
});
}
}
public class UnifiedNativeAdViewHolder extends RecyclerView.ViewHolder {
private UnifiedNativeAdView adView;
private TextView textLoading;
private CardView adContainer;
public UnifiedNativeAdView getAdView() {
return adView;
}
UnifiedNativeAdViewHolder(View view) {
super(view);
textLoading = view.findViewById(R.id.native_loading_text);
adView = view.findViewById(R.id.native_ad_view);
adContainer = view.findViewById(R.id.ad_unified_conatiner);
// The MediaView will display a video asset if one is present in the ad, and the
// first image asset otherwise.
adView.setMediaView((MediaView) adView.findViewById(R.id.ad_media));
// Register the view used for each individual asset.
adView.setHeadlineView(adView.findViewById(R.id.ad_headline));
adView.setBodyView(adView.findViewById(R.id.ad_body));
adView.setCallToActionView(adView.findViewById(R.id.ad_call_to_action));
adView.setIconView(adView.findViewById(R.id.ad_icon));
adView.setPriceView(adView.findViewById(R.id.ad_price));
adView.setStarRatingView(adView.findViewById(R.id.ad_stars));
adView.setStoreView(adView.findViewById(R.id.ad_store));
adView.setAdvertiserView(adView.findViewById(R.id.ad_advertiser));
}
}
}
surprised there is no answer here.
The approach I would use outside of the recyclerview adapter:
adLoader.loadAds(new AdRequest.Builder().build(), NUMBER_OF_ADS_TO_LOAD(Max 5 according to docs);
instead usual adLoader.loadAd
and then
builder.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
// OnUnifiedNativeAdLoadedListener implementation.
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
nativeAds.add(unifiedNativeAd);
}
});
where
private List<UnifiedNativeAd> nativeAds = new ArrayList<>();
which you pass to your recyclerview adapter and mix in your other items.
This will need some memory handling with destroy called before you request another list etc. but the idea is to preload a list of ads instead of loading them while scrolling
I am trying to build my 1st app, and want to insert an admob native ad in a recyclerview.
I have created the viewpager from android studio's default tabbed activity, and have inserted a recyclerview, which is working fine.
Now, from AdMob Native Advanced Ads in an Android Feed I am trying to insert a native ad.
But, the codelab example uses Fragment Transaction. Do I must need to implement that?
It will be helpful for me, if I can implement the complete ad related part in the fragment only (except the initialisation).
Here is my current status of the fragment:
public class SunFragment extends Fragment {
public static final int NUMBER_OF_ADS = 1;
private AdLoader adLoader;
private List<Object> mRecyclerViewItems = new ArrayList<>();
private List<UnifiedNativeAd> mNativeAds = new ArrayList<>();
ArrayList<Object> sunsList;
Typeface sunfont;
Double Dlat;
Double Dlang;
//to be called by the MainActivity
public SunFragment() {
// Required empty public constructor
}
private static final String KEY_LOCATION_NAME = "location_name";
public String TAG = "SunFragment";
public String location;//="No location name found";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
location = savedInstanceState.getCharSequence(KEY_LOCATION_NAME).toString();
}
setRetainInstance(true);
}
public List<Object> getRecyclerViewItems() {
return mRecyclerViewItems;
}
private void loadNativeAds() {
AdLoader.Builder builder = new AdLoader.Builder(getContext(), getString(R.string.ad_unit_id));
adLoader = builder.forUnifiedNativeAd(
new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
// A native ad loaded successfully, check if the ad loader has finished loading
// and if so, insert the ads into the list.
mNativeAds.add(unifiedNativeAd);
if (!adLoader.isLoading()) {
//insertAdsInMenuItems();
mRecyclerViewItems.add(3, mNativeAds);
}
}
}).withAdListener(
new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// A native ad failed to load, check if the ad loader has finished loading
// and if so, insert the ads into the list.
Log.e("MainActivity", "The previous native ad failed to load. Attempting to"
+ " load another.");
if (!adLoader.isLoading()) {
//insertAdsInMenuItems();
}
}
}).build();
// Load the Native ads.
adLoader.loadAds(new AdRequest.Builder().build(), NUMBER_OF_ADS);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
//onSaveInstanceState(new Bundle());
if (getArguments() != null) {
Dlat = getArguments().getDouble("loclat");
Dlang = getArguments().getDouble("loclang");
} else {
Dlat = 0.0;
Dlang = 0.0;
}
View rootView = inflater.inflate(R.layout.fragment_sun, container, false);
RecyclerView rv = rootView.findViewById(R.id.rv_recycler_view);
rv.setNestedScrollingEnabled(false);
rv.setHasFixedSize(true);
RecyclerView.LayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
// System.out.println("location " + location);
setRetainInstance(true);
RecyclerView.Adapter adapter = new SunAdapter(getContext(), sunsList);
rv.setAdapter(adapter);
return rootView;
}
#Override
public void onSaveInstanceState(Bundle locState) {
super.onSaveInstanceState(locState);
if (location != null) {
locState.putCharSequence(KEY_LOCATION_NAME, location);
}
}
}
and the adapter is:
public class SunAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final Context mContext;
private final ArrayList<Object> mSunsList;
private static final int MENU_ITEM_VIEW_TYPE = 0;
private static final int UNIFIED_NATIVE_AD_VIEW_TYPE = 1;
public SunAdapter(Context context, ArrayList<Object> sunsList) {
this.mContext = context;
this.mSunsList = sunsList;
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private TextView textViewId;
private TextView textViewSicon;
private TextView textViewStime;
private TextView textViewEicon;
private TextView textViewEtime;
private TextView ntextViewSicon;
private TextView ntextViewStime;
private TextView ntextViewEicon;
private TextView ntextViewEtime;
MyViewHolder(View itemView) {
super(itemView);
textViewId = itemView.findViewById(R.id.tv_city);
textViewSicon = itemView.findViewById(R.id.tv_MSicon);
textViewStime = itemView.findViewById(R.id.tv_MStime);
textViewEicon = itemView.findViewById(R.id.tv_MEicon);
textViewEtime = itemView.findViewById(R.id.tv_MEtime);
ntextViewSicon = itemView.findViewById(R.id.tv_NSicon);
ntextViewStime = itemView.findViewById(R.id.tv_NStime);
ntextViewEicon = itemView.findViewById(R.id.tv_NEicon);
ntextViewEtime = itemView.findViewById(R.id.tv_NEtime);
// mSportsImage = itemView.findViewById(R.id.sportsImage);
}
}
#Override
public int getItemCount() {
return mSunsList.size();
}
#Override
public int getItemViewType(int position) {
Object sunList = mSunsList.get(position);
if (sunList instanceof UnifiedNativeAd) {
return UNIFIED_NATIVE_AD_VIEW_TYPE;
}
return MENU_ITEM_VIEW_TYPE;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
switch (viewType) {
case UNIFIED_NATIVE_AD_VIEW_TYPE:
View unifiedNativeLayoutView = LayoutInflater.from(
viewGroup.getContext()).inflate(R.layout.ad_unified,
viewGroup, false);
return new UnifiedNativeAdViewHolder(unifiedNativeLayoutView);
case MENU_ITEM_VIEW_TYPE:
// Fall through.
default:
View menuItemLayoutView = LayoutInflater.from(viewGroup.getContext()).inflate(
R.layout.card_item, viewGroup, false);
return new MyViewHolder(menuItemLayoutView);
}
}
// #RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType) {
case UNIFIED_NATIVE_AD_VIEW_TYPE:
UnifiedNativeAd nativeAd = (UnifiedNativeAd) mSunsList.get(position);
populateNativeAdView(nativeAd, ((UnifiedNativeAdViewHolder) holder).getAdView());
break;
case MENU_ITEM_VIEW_TYPE:
// fall through
default:
MyViewHolder myViewHolder = (MyViewHolder) holder;
SunSession sunSession = (SunSession) mSunsList.get(position);
myViewHolder.textViewId.setText(sunSession.getId());
myViewHolder.textViewSicon.setText(HtmlCompat.fromHtml(sunSession.getSicon(), HtmlCompat.FROM_HTML_MODE_LEGACY));
myViewHolder.textViewStime.setText(sunSession.getStime());
myViewHolder.textViewEicon.setText(HtmlCompat.fromHtml(sunSession.getEicon(), HtmlCompat.FROM_HTML_MODE_LEGACY));
myViewHolder.textViewEtime.setText(sunSession.getEtime());
myViewHolder.ntextViewSicon.setText(HtmlCompat.fromHtml(sunSession.getNSicon(), HtmlCompat.FROM_HTML_MODE_LEGACY));
myViewHolder.ntextViewStime.setText(sunSession.getNStime());
myViewHolder.ntextViewEicon.setText(HtmlCompat.fromHtml(sunSession.getNEicon(), HtmlCompat.FROM_HTML_MODE_LEGACY));
myViewHolder.ntextViewEtime.setText(sunSession.getNEtime());
}
}
private void populateNativeAdView(UnifiedNativeAd nativeAd,
UnifiedNativeAdView adView) {
// Some assets are guaranteed to be in every UnifiedNativeAd.
((TextView) adView.getHeadlineView()).setText(nativeAd.getHeadline());
((TextView) adView.getBodyView()).setText(nativeAd.getBody());
((Button) adView.getCallToActionView()).setText(nativeAd.getCallToAction());
// These assets aren't guaranteed to be in every UnifiedNativeAd, so it's important to
// check before trying to display them.
NativeAd.Image icon = nativeAd.getIcon();
if (icon == null) {
adView.getIconView().setVisibility(View.INVISIBLE);
} else {
((ImageView) adView.getIconView()).setImageDrawable(icon.getDrawable());
adView.getIconView().setVisibility(View.VISIBLE);
}
if (nativeAd.getPrice() == null) {
adView.getPriceView().setVisibility(View.INVISIBLE);
} else {
adView.getPriceView().setVisibility(View.VISIBLE);
((TextView) adView.getPriceView()).setText(nativeAd.getPrice());
}
if (nativeAd.getStore() == null) {
adView.getStoreView().setVisibility(View.INVISIBLE);
} else {
adView.getStoreView().setVisibility(View.VISIBLE);
((TextView) adView.getStoreView()).setText(nativeAd.getStore());
}
if (nativeAd.getStarRating() == null) {
adView.getStarRatingView().setVisibility(View.INVISIBLE);
} else {
((RatingBar) adView.getStarRatingView())
.setRating(nativeAd.getStarRating().floatValue());
adView.getStarRatingView().setVisibility(View.VISIBLE);
}
if (nativeAd.getAdvertiser() == null) {
adView.getAdvertiserView().setVisibility(View.INVISIBLE);
} else {
((TextView) adView.getAdvertiserView()).setText(nativeAd.getAdvertiser());
adView.getAdvertiserView().setVisibility(View.VISIBLE);
}
// Assign native ad object to the native view.
adView.setNativeAd(nativeAd);
}
}
with this situation, the normal recyclerview is working, but no ad is inserted.
It will be really helpful if somebody shows me how to insert the ad, following the codelab, which probably means, how to implemeant this section in my fragment.
I have a list made with RecyclerView. I can add the ad to the bottom, but I get an error when I want to add it to the middle.
For example, I can't add the ad to line 2. I get error again when I increase getItemCount value by 1 (return movies.size() + 1). What I haven't tried.
My Adapter
public class SeriesActivityAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Movies> movies;
private static final int ITEM = 0;
private static final int BANNER = 1;
TinyDB tinyDB;
private Activity context;
public SeriesActivityAdapter(Activity c, List<Movies> movies) {
this.movies= movies;
this.context = c;
tinyDB = new TinyDB(c);
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if(viewType==BANNER && !tinyDB.getBoolean("remove_ads")){
View view = LayoutInflater.from(context).inflate(R.layout.item_ad, parent,false);
return new MyViewBanner(view);
}
else{
View view = LayoutInflater.from(context).inflate(R.layout.item_series_activity, parent,false);
return new MyViewHolder(view);
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, final int position) {
if(holder instanceof MyViewHolder){
final Movies currentMovie = movies.get(position);
final MyViewHolder myholder = (MyViewHolder) holder;
Glide.with(context)
.load(currentMovie.getResim())
.into(myholder.movieImage);
}
else if (holder instanceof MyViewBanner){
final MyViewBanner myBanner = (MyViewBanner) holder;
AdRequest adRequest = new AdRequest.Builder().build();
myBanner.adView.loadAd(adRequest);
}
}
#Override
public int getItemCount() {
return movies.size() + 1;
}
#Override
public int getItemViewType(int position) {
if(position == 2){
return BANNER;
}
return ITEM;
}
}
My Activity
JsonArrayRequest arrayRequest = new JsonArrayRequest(murl,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray jsonArray) {
Log.i("log-",jsonArray.toString());
for(int i = 0; i < jsonArray.length(); i++) {
try {
JSONObject jsonObject = jsonArray.getJSONObject(i);
users.add(new Movies(jsonObject.getString("link"),
jsonObject.getString("resim"),
"",jsonObject.getString("tip")));
}
catch(JSONException e) {
Log.i("log-","error"+e.getMessage());
}
}
moviesAdapter.notifyDataSetChanged();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {...
}
});
Volley.newRequestQueue(this).add(arrayRequest);
My Logcat
Process: com.moktay.izliyoo, PID: 23423
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:411)
at com.moktay.izliyoo.list.SeriesActivityAdapter.onBindViewHolder(SeriesActivityAdapter.java:64)
Pass null in Arraylist at the position where you want to show ads in recyler view.
Suppose at 2 and 4 position you want ads simplly add null at those position and finally in itemViewType method check for
if(arraylist.get(position)==null)
{
return BANNER
}else{
return VIEWTYPE
}
I am using Recyclerview with multiple ViewTypes.I have two Model classes for two different type of item in recyclerview as.I want to display two different type of item in same RecyclerView
My RecyclerViewAdapter is
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
ArrayList<OneView> oneList;
ArrayList<TwoView> twoList;
public RecyclerAdapter(Context context,ArrayList<OneView> oneList,ArrayList<TwoView> twoList){
this.context=context;
this.oneList=oneList;
this.twoList=twoList;
}
#Override
public int getItemViewType(int position) {
switch (position){
case 0:
return 0;
case 1:
return 1;
}
return -1;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
int layout=0;
RecyclerView.ViewHolder viewHolder;
if(viewType==0){
layout=R.layout.oneview;
View one= LayoutInflater.from(parent.getContext()).inflate(layout,parent,false);
return new ViewHolder(one);
}else if(viewType==1){
layout=R.layout.twoview;
View two= LayoutInflater.from(parent.getContext()).inflate(layout,parent,false);
return new SecondView(two);
}else {
return null;
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int viewType=holder.getItemViewType();
switch (viewType){
case 0:
OneView oneView=oneList.get(position);
((ViewHolder)holder).name.setText(oneView.getName());
break;
case 1:
TwoView twoView=twoList.get(position);
((SecondView)holder).name.setText(twoView.getName());
((SecondView)holder).address.setText(twoView.getAddress());
break;
default:
break;
}
}
#Override
public int getItemCount() {
return (this.oneList.size()+this.twoList.size());
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView name;
public ViewHolder(View itemView) {
super(itemView);
name=(TextView)itemView.findViewById(R.id.nameOne);
}
}
public class SecondView extends RecyclerView.ViewHolder {
private TextView name,address;
public SecondView(View itemView) {
super(itemView);
name=(TextView)itemView.findViewById(R.id.nameTwo);
address=(TextView)itemView.findViewById(R.id.address);
}
}
}
I want to display two type of item in same RecyclerView.But I am getting Attempt to write to field 'int android.support.v7.widget.RecyclerView$ViewHolder.mItemViewType' on a null object reference exception. How to resolve this ?
here is the complete example. I've used a RecyclerView with Multiple View Type. My scenario was, I have to show "cuisine list" [which is a horizontal view of multiple cuisines], then "number of restaurant", then "restaurant list".
so, i've used VIEW_RESTAURANT for restaurant view, VIEW_CUISINE for cuisine, VIEW_INFO for number of restaurant. As for my case, there's pagination, so VIEW_PROGRESS is used for showing progress bar at the bottom [by that time new set of data is fetch, if avaiable], VIEW_NO_DATA is used if restaurant list is empty.
hopefully from here, You can manage based on your requirement.
public class HomeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private String TAG = HomeAdapter.class.getSimpleName();
class ViewType {
int VIEW_PROGRESS = 1;
int VIEW_NO_DATA = 2;
int VIEW_RESTAURANT = 3;
int VIEW_CUISINE = 4;
int VIEW_INFO = 6;
}
private ViewType mViewType = new ViewType();
private Context mContext;
private int mCuisineItem = 1;
private int mInfoItem = 1;
private int mShowNoItem = 0;
private boolean mIsLoading;
private int mRestaurantNumber;
private int mCurrentPage;
private List<Data> mDataList;
private List<CuisineData> mCuisines;
private PaginationListener mPaginationListener;
private HorizontalPaginationListener mHorizontalPaginationListener;
private SearchResultClickListener mSearchResultClickListener;
private String mFrom;
public HomeAdapter(Context context, List<Data> dataList, List<CuisineData> cuisines, RecyclerView recyclerView, SearchResultClickListener searchResultClickListener) {
mContext = context;
mDataList = dataList;
mCuisines = cuisines;
mSearchResultClickListener = searchResultClickListener;
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
final LinearLayoutManager llManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visible_threshold = 1;
int total_item_count = llManager.getItemCount();
int last_visible_item = llManager.findLastVisibleItemPosition();
if (!mIsLoading && total_item_count <= (last_visible_item + visible_threshold)) {
if (mPaginationListener != null) mPaginationListener.onPagination();
mIsLoading = true;
}
}
});
}
}
public void setmPaginationListener(PaginationListener paginationListener) {
mPaginationListener = paginationListener;
}
public void setmHorizontalPaginationListener(HorizontalPaginationListener horizontalPaginationListener) {
mHorizontalPaginationListener = horizontalPaginationListener;
}
public void setLoaded() {
mIsLoading = false;
}
public void setmRestaurantNumber(int restaurantNumber) {
mRestaurantNumber = restaurantNumber;
}
public void setmCurrentPage(int currentPage) {
mCurrentPage = currentPage;
}
public void addCuisine(String from) {
mFrom = from;
notifyDataSetChanged();
}
public void addCuisines(List<CuisineData> cuisines, String from) {
mFrom = from;
mCuisines.clear();
mCuisines = cuisines;
notifyDataSetChanged();
}
public void addRestaurants(List<Data> dataList) {
mShowNoItem = 0;
if(mCurrentPage == 1) notifyItemChanged(1);
if (mCurrentPage == 1) notifyItemChanged(2);
int insert_index = mDataList.size();
int pos_start = insert_index + mCuisineItem + mInfoItem;
mDataList.addAll(insert_index, dataList);
notifyItemRangeInserted(pos_start, dataList.size());
}
public void removeRestaurants() {
mShowNoItem = 1;
mDataList.clear();
mDataList = new ArrayList<>();
notifyItemRangeRemoved(mCuisineItem + mInfoItem, mDataList.size());
notifyItemChanged(2);
}
public void addProgressBar(Data data) {
mDataList.add(data);
notifyItemInserted(getItemCount() - 1);
}
public void removeProgressBar() {
if (mDataList.size() > 0) {
mDataList.remove(mDataList.size() - 1);
notifyItemRemoved(mCuisineItem + mInfoItem + mDataList.size());
}
}
public void removeAll() {
mDataList.clear();
mCuisines.clear();
mShowNoItem = 0;
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return mDataList.size() + mShowNoItem + mCuisineItem + mInfoItem;
}
#Override
public int getItemViewType(int position) {
if (position == 0) return mViewType.VIEW_CUISINE;
if (position == 1) return mViewType.VIEW_INFO;
return mShowNoItem == 0 ? (mDataList.get(position - (mCuisineItem + mInfoItem)) != null ? mViewType.VIEW_RESTAURANT : mViewType.VIEW_PROGRESS)
: mViewType.VIEW_NO_DATA;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == mViewType.VIEW_CUISINE) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_horizontal_cuisines, parent, false);
return new ViewHolderCuisinesList(mContext, view, mHorizontalPaginationListener);
}
if (viewType == mViewType.VIEW_INFO) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_restaurant_number, parent, false);
return new ViewHolderRestaurantNumber(mContext, view);
}
if (mShowNoItem == 0) {
if (viewType == mViewType.VIEW_RESTAURANT) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.food_item_nearest_restaurant, parent, false);
return new ViewHolderRestaurant(mContext, view, mSearchResultClickListener);
} else if (viewType == mViewType.VIEW_PROGRESS) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_progress, parent, false);
return new ViewHolderProgress(view);
}
} else {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_empty, parent, false);
return new ViewHolderEmpty(view);
}
return null;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof ViewHolderSearch) {
((ViewHolderSearch) holder).onBind();
}
if (holder instanceof ViewHolderCuisinesList) {
if (!TextUtils.isEmpty(mFrom)) {
if (mFrom.equalsIgnoreCase(AppConstants.CUISINES))
((ViewHolderCuisinesList) holder).onBind(mCuisines);
else if (mFrom.equalsIgnoreCase(AppConstants.CUISINE))
((ViewHolderCuisinesList) holder).onBind_();
}
}
if (holder instanceof ViewHolderRestaurantNumber) {
((ViewHolderRestaurantNumber) holder).onBind(mRestaurantNumber);
}
if (mShowNoItem == 0) {
if (holder instanceof ViewHolderRestaurant) {
((ViewHolderRestaurant) holder).onBind(position - (mCuisineItem + mInfoItem), mDataList.get(position - (mCuisineItem + mInfoItem)));
} else if (holder instanceof ViewHolderProgress) {
((ViewHolderProgress) holder).onBind();
}
} else {
if (holder instanceof ViewHolderEmpty) {
((ViewHolderEmpty) holder).onBind(mContext.getString(R.string.no_result_found));
}
}
}
}
I am showing banner ads within my android app. I followed official doc for implementing admob banner contentView ads and I successfully loaded ads but now my recyclerview starts lagging like hell. If i remove ads from my code scroll becomes smooth. Please help me with this problem.
Here's my fragment class
public class WallpaperFragment extends Fragment {
private RecyclerView recyclerView;
private DatabaseReference wallRef;
private String category;
private FirebaseAuth mAuth;
private final String CATEGORY = "Category";
private Context context;
private ArrayList<Object> modelList = new ArrayList<>();
private GridLayoutManager manager;
// The number of native ads to load and display.
public int NUMBER_OF_ADS = 5;
// List of native ads that have been successfully loaded.
private List<NativeAd> mNativeAds = new ArrayList<>();
private WallpaperAdapter adapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fg_wallpaper, container, false);
category = "Recent";
init(view);
Util.showDialog(context, "Loading wallpapers...");
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return (position % (SPACE_BETWEEN_ADS + 1) == SPACE_BETWEEN_ADS) ? 2 : 1;
}
});
setScrollListener();
initializeFirebaseDatabase();
return view;
}
private void init(View view) {
context = getContext();
MobileAds.initialize(context, getString(R.string.admob_app_id));
wallRef = FirebaseDatabase.getInstance().getReference().child(WALL).child(CATEGORY).child(category).getRef();
mAuth = FirebaseAuth.getInstance();
recyclerView = view.findViewById(R.id.recyclerView);
manager = new GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(manager);
recyclerView.addItemDecoration(new GridItemDecor(0));
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(null);
}
private void setScrollListener() {
recyclerView.addOnScrollListener(new HidingScrollListener() {
#Override
public void onHide() {
if (context instanceof ToolbarShowHideListener) {
((ToolbarShowHideListener) context).hideBottomNavigation();
}
}
#Override
public void onShow() {
if (context instanceof ToolbarShowHideListener) {
((ToolbarShowHideListener) context).showBottomNavigation();
}
}
});
}
private void initializeFirebaseDatabase() {
mNativeAds.clear();
wallRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
modelList.clear();
for (DataSnapshot childDataSnapshot : dataSnapshot.getChildren()) {
WallpaperModel model = childDataSnapshot.getValue(WallpaperModel.class);
modelList.add(model);
}
NUMBER_OF_ADS = modelList.size() / 2;
loadNativeAd();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void loadNativeAd() {
loadNativeAd(0);
}
private void insertAdsInMenuItems() {
if (mNativeAds.size() <= 0) {
return;
}
int offset = (modelList.size() / mNativeAds.size()) + 1;
int index = 2;
for (NativeAd ad : mNativeAds) {
modelList.add(index, ad);
index = index + offset;
}
if (adapter == null) {
adapter = new WallpaperAdapter(context, modelList, Objects.requireNonNull(mAuth.getCurrentUser()).getUid(), true, WALLPAPER_FRAGMENT);
recyclerView.setAdapter(adapter);
} else {
adapter.updateList(modelList);
}
}
private void loadNativeAd(final int adLoadCount) {
if (adLoadCount >= NUMBER_OF_ADS) {
insertAdsInMenuItems();
return;
}
AdLoader.Builder builder = new AdLoader.Builder(context, /*getString(R.string.ad_unit_id)*/"ca-app-pub-3940256099942544/2247696110");
AdLoader adLoader = builder.forContentAd(new NativeContentAd.OnContentAdLoadedListener() {
#Override
public void onContentAdLoaded(NativeContentAd ad) {
// A content ad loaded successfully, call this method again to
// load the next ad in the items list.
mNativeAds.add(ad);
loadNativeAd(adLoadCount + 1);
}
}).withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
// A native ad failed to load. Call this method again to load
// the next ad in the items list.
Log.e("MainActivity", "The previous native ad failed to load. Attempting to" +
" load another.");
loadNativeAd(adLoadCount + 1);
}
}).build();
// Load the Native Express ad.
adLoader.loadAd(new AdRequest.Builder().addTestDevice("9F50A23B86C21B90330202FAECE3C331").build());
}
}
and here's my adapter class,
public class WallpaperAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private int height, fragment_id;
private String uId;
private Animation fadeout, fadein;
private DatabaseReference favCheckRef;
private final String CATEGORY = "Category";
private ArrayList<Object> modelList;
private boolean showLikeBtn;
public WallpaperAdapter(Context context, ArrayList<Object> modelList, String uId, boolean showLikeBtn, int fragment_id) {
this.context = context;
this.modelList = modelList;
this.uId = uId;
this.showLikeBtn = showLikeBtn;
height = context.getResources().getDisplayMetrics().heightPixels;
fadeout = AnimationUtils.loadAnimation(context, R.anim.anim_fade_out);
fadein = AnimationUtils.loadAnimation(context, R.anim.anim_fade_in);
favCheckRef = FirebaseDatabase.getInstance().getReference().child(WALL).child(USER)
.child(uId).child(FAVOURITES).getRef();
this.fragment_id = fragment_id;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case NATIVE_CONTENT_AD_VIEW_TYPE:
View nativeContentLayoutView = LayoutInflater.from(
parent.getContext()).inflate(R.layout.ad_content,
parent, false);
return new NativeContentAdViewHolder(nativeContentLayoutView);
case MENU_ITEM_VIEW_TYPE:
// Fall through.
default:
View dataView = LayoutInflater.from(context).inflate(R.layout.single_wallpaper_unit, parent, false);
return new ViewHolder(dataView);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
int viewType = getItemViewType(position);
Util.dismissDialog();
switch (viewType) {
case NATIVE_CONTENT_AD_VIEW_TYPE:
NativeContentAd contentAd = (NativeContentAd) modelList.get(position);
populateAdView(contentAd, (NativeContentAdView) holder.itemView);
break;
case MENU_ITEM_VIEW_TYPE:
// fall through
default:
final ViewHolder wallHolder = (ViewHolder) holder;
WallpaperModel model = (WallpaperModel) modelList.get(position);
wallHolder.wallpaper.getLayoutParams().height = (int) (height / 2.5);
wallHolder.name.setText(model.getName());
favCheck(wallHolder, model);
Glide.with(wallHolder.wallpaper.getContext())
.load(model.getThumbnail())
.into(wallHolder.wallpaper);
break;
}
}
#Override
public int getItemViewType(int position) {
Object recyclerViewItem = modelList.get(position);
if (recyclerViewItem instanceof NativeContentAd) {
return NATIVE_CONTENT_AD_VIEW_TYPE;
}
return MENU_ITEM_VIEW_TYPE;
}
#Override
public int getItemCount() {
return modelList.size();
}
private void populateAdView(NativeContentAd ad,NativeContentAdView adView){
((TextView) adView.getHeadlineView()).setText(ad.getHeadline());
List<NativeAd.Image> images = ad.getImages();
if (images.size() > 0) {
((ImageView) adView.getImageView()).setImageDrawable(images.get(0).getDrawable());
}
adView.setNativeAd(ad);
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView name;
ImageView wallpaper, favouriteIcon;
private ViewHolder(View itemView) {
super(itemView);
wallpaper = itemView.findViewById(R.id.wallpaper);
name = itemView.findViewById(R.id.name);
favouriteIcon = itemView.findViewById(R.id.favouriteIcon);
}
}
public class NativeContentAdViewHolder extends RecyclerView.ViewHolder {
NativeContentAdViewHolder(View view) {
super(view);
NativeContentAdView adView = (NativeContentAdView) view;
adView.setHeadlineView(adView.findViewById(R.id.contentad_headline));
adView.setImageView(adView.findViewById(R.id.contentad_image));
}
}
}
You are loading native express, not banner.
The problem is the ads have images, just like a normal viewholder, you have to handel the caching of the images, I see you already use glide...
Also, it's not a good idea showing your ad ID.
Last thing, NONE of this matters because native express ads are deprecated and will anyway not work.
Another option is to use Native Ads Advance, but unless you have a few million downloads you will not be able to use it - look here:
Note: Native Ads Advanced is currently released to a limited set of publishers. If you're interested in participating, reach out to your account manager to discuss the possibility.
What I would suggest is using some ad provider like Appodeal which supports native ads.