Native
Native ad is a flexible type of advertising. You can adapt the display to your UI by preparing a template.
Appodeal provides 4 options to implement the layout of native ads 3 templates + your custom
implementation
All of them are inherited from the same NativeAdView class.
NativeAdView consists of the following components:
NativeIconView- Icon of the native ad.AdAttributionView- Advertising Indicator. This is a TextView labeled "Ad".TitleVIew- Title of the native ad.DescriptionView- Text descriptionView of the native ad.RatingBarView- Rating of the app in [0-5] range.NativeMediaView- Media content of the native ad.CallToActionView- Button for click.AdChoiceView- Special ad icon provided by ad network.
Templates implementation:
To display them, all you need to do is:
- Create programmatically or in your layout file one of View template classes
 
Native template views classes:
NativeAdViewNewsFeed
NativeAdViewAppWall
NativeAdViewContentStream
NativeAdView for custom implementation:
To display it, all you need to do is:
- Create a 
NativeAdVIewclass programmatically or in your layout file - Inside the created 
NativeAdView, arrange all theView/IconView/MediaViewyou need for displaying it in any style you prefer - Bind programmatically or in your layout file all necessary 
View/IconView/MediaView. 
Native view for a Custom Implementation:
NativeAdView
You can use our demo app as a reference project.
Native Demo
Integration guide
- For templates
 - For custom layout
 
- Create programmatically or in your layout file one of View template classes:
 
- XML
 - Kotlin
 - Java
 
<com.appodeal.ads.nativead.NativeAdViewNewsFeed
    android:id="@+id/native_news_feed"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
<com.appodeal.ads.nativead.NativeAdViewAppWall
    android:id="@+id/native_app_wall"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
<com.appodeal.ads.nativead.NativeAdViewContentStream
    android:id="@+id/native_content_stream"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
val newsFeedView = NativeAdViewNewsFeed(context)
val appWallView = NativeAdViewAppWall(context)
val contentStreamView = NativeAdViewContentStream(context)
NativeAdViewNewsFeed newsFeedView = new NativeAdViewNewsFeed(context);
NativeAdViewAppWall appWallView = new NativeAdViewAppWall(context);
NativeAdViewContentStream contentStreamView = new NativeAdViewContentStream(context);
- Get a view instance from layout OR add a programmatically created ViewTemplate to your View hierarchy:
 
- Kotlin
 - Java
 
val newsFeedView = findViewById<NativeAdViewNewsFeed>(R.id.native_news_feed);
val appWallView = findViewById<NativeAdViewAppWall>(R.id.native_app_wall);
val contentStreamView = findViewById<NativeAdViewContentStream>(R.id.native_content_stream);
rootView.addView(newsFeedView)
rootView.addView(appWallView)
rootView.addView(contentStreamView)
NativeAdViewNewsFeed newsFeedView = findViewById(R.id.native_news_feed);
NativeAdViewAppWall appWallView = findViewById(R.id.native_app_wall);
NativeAdViewContentStream contentStreamView = findViewById(R.id.native_content_stream);
rootView.addView(newsFeedView);
rootView.addView(appWallView);
rootView.addView(contentStreamView);
- When the NativeAd is loaded just register it
 
- For single NativeAd
 - For several NativeAd instances
 
- Kotlin
 - Java
 
if (Appodeal.isLoaded(Appodeal.NATIVE)) {
  newsFeedView.registerView(Appodeal.getNativeAdCount(1))
}
if (Appodeal.isLoaded(Appodeal.NATIVE)) {
  newsFeedView.registerView(Appodeal.getNativeAdCount(1));
}
- Kotlin
 - Java
 
val needToShow = 3
if (Appodeal.getAvailableNativeAdsCount() >= needToShow) {
    val nativeAds = Appodeal.getNativeAdCount(needToShow)
    newsFeedView.registerView(nativeAds[0])
    appWallView.registerView(nativeAds[1])
    contentStreamView.registerView(nativeAds[2])
}
int needToShow = 3;
if (Appodeal.getAvailableNativeAdsCount() >= needToShow) {
    List<NativeAd> nativeAds = Appodeal.getNativeAdCount(needToShow);
    newsFeedView.registerView(nativeAds.get(0));
    appWallView.registerView(nativeAds.get(1));
    contentStreamView.registerView(nativeAds.get(2);
}
- When the display has been terminated and you no longer plan to use the NativeAdView, you should call the destroy method:
 
- Kotlin
 - Java
 
nativeAdView.destroy()
nativeAdView.destroy();
General requirements:
NativeAdViewmust have min height as 32dp;NativeMediaViewmust have mim size as 120dp x 120dp;- The 
AdAttributionViewmust clearly mark your nativeAd as "Ad" so that users don't mistake them for content; - You are allowed to scale the 
NativeIconVieworNativeMediaViewdown without modifying the aspect ratio; - You are allowed to crop the 
NativeIconVieworNativeMediaViewsymmetrically by up to 20% in only one dimension (height or width). 
- Create your markdown with NativeAdView as root:
 
You can build a layout with any style, arrangement of elements and with any type of
ViewGroup(ConstrainLayout, RelativeLayout, FrameLayout)
<?xml version="1.0" encoding="utf-8"?>
<com.appodeal.ads.nativead.NativeAdView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nativeAdView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:adChoicePosition="end_top"
    app:callToActionViewId="@id/callToActionView"
    app:descriptionViewId="@id/descriptionView"
    app:iconViewId="@id/iconView"
    app:mediaViewId="@id/mediaView"
    app:ratingViewId="@id/ratingView"
    app:titleViewId="@id/titleView"
    app:adAttributionViewId="@+id/ad_attribution">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <com.appodeal.ads.nativead.NativeIconView
                android:id="@+id/iconView"
                android:layout_width="90dp"
                android:layout_height="90dp"
                android:layout_gravity="center_vertical"
                android:layout_margin="5dp" />
            <TextView
                android:id="@+id/ad_attribution"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textColor="@color/black"
                android:background="@color/red" />
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">
                    <TextView
                        android:id="@+id/titleView"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"/>
                </LinearLayout>
                <TextView
                    android:id="@+id/descriptionView"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:maxLines="3" />
                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="horizontal">
                    <LinearLayout
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_vertical"
                        android:layout_weight="1"
                        android:orientation="horizontal">
                        <RatingBar
                            android:id="@+id/ratingView"
                            style="?android:attr/ratingBarStyleSmall"
                            android:layout_width="wrap_content"
                            android:layout_height="wrap_content" />
                    </LinearLayout>
                    <Button
                        android:id="@+id/callToActionView"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:minHeight="30dp" />
                </LinearLayout>
            </LinearLayout>
        </LinearLayout>
        <com.appodeal.ads.nativead.NativeMediaView
            android:id="@+id/mediaView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</com.appodeal.ads.nativead.NativeAdView>
Requirements for NativeAdView elements
| Name of view | Type | Mandatory | Description | 
|---|---|---|---|
titleView | TextView | Mandatory | Title of the native ad. Maximum 25 symbols of the title should always be displayed. You can add ellipsis at the end if the title is longer. | 
callToActionView | Button | Mandatory | Call-to-action button. Should be displayed without truncation on a visible button. | 
descriptionView | TextView | Optional | Text description of the native ad. If you choose to display the description, you should display maximum 100 characters. You can add ellipsis at the end. | 
ratingView | RatingBar | Optional | Rating of the app in [0-5] range | 
adAttributionView | TextView | Mandatory | Advertising Indicator. This is a TextView labeled "Ad". You can specify the color of the text and background. See adAttribution settings. You can place it anywhere inside the NativeAdView. | 
adChoicesView | ViewGroup | Attach automatically | Special ad icon provided by ad network. If SDK received AdChoice from ad network, it attached it automatically. You can specify a position in one of the corners of the NativeAdView. See setAdChoice position | 
iconView | NativeIconView | Mandatory/Optional | Media content of the native ad. | 
mediaView | NativeMediaView | Mandatory/Optional | Icon of the native ad. | 
NativeAdView must contain either NativeIconView or NativeMediaView.
The titleView, callToActionView and adAttributionView has to be added in any cases.
- Set ids of all child views of 
NativeAdView. 
You can do this either in the xml file of markdown (recommended way) or programmatically
- XML
 - Kotlin
 - Java
 
<com.appodeal.ads.nativead.NativeAdView
    app:callToActionViewId="@id/callToActionView"
    app:descriptionViewId="@id/descriptionView"
    app:iconViewId="@id/iconView"
    app:mediaViewId="@id/mediaView"
    app:ratingViewId="@id/ratingView"
    app:titleViewId="@id/titleView">
    app:adAttributionViewId="@id/adAttribution">
val nativeAdView: NativeAdView = ...
nativeAdView.titleViewId = R.id.titleView
nativeAdView.callToActionViewId = R.id.callToActionView
nativeAdView.descriptionViewId = R.id.descriptionView
nativeAdView.ratingViewId = R.id.ratingView
nativeAdView.iconViewId = R.id.iconView
nativeAdView.mediaViewId = R.id.mediaView
nativeAdView.adAttributionViewId = R.id.adAttribution
// OR
nativeAdView.titleView = findViewById(R.id.titleView)
nativeAdView.callToActionView = findViewById(R.id.callToActionView)
nativeAdView.descriptionView = findViewById(R.id.descriptionView)
nativeAdView.ratingView = findViewById(R.id.ratingView)
nativeAdView.iconView = findViewById(R.id.iconView)
nativeAdView.mediaView = findViewById(R.id.mediaView)
nativeAdView.adAttributionView = findViewById(R.id.adAttribution)
NativeAdView nativeAdView: NativeAdView = ...
nativeAdView.setTitleViewId(R.id.titleView);
nativeAdView.setCallToActionViewId(R.id.callToActionView);
nativeAdView.setDescriptionViewId(R.id.descriptionView);
nativeAdView.setRatingViewId(R.id.ratingView);
nativeAdView.setIconViewId(R.id.iconView);
nativeAdView.setMediaViewId(R.id.mediaView);
nativeAdView.setAdAttributionViewId(R.id.adAttribution);
// OR
nativeAdView.setTitleView(findViewById(R.id.titleView));
nativeAdView.setCallToActionView(findViewById(R.id.callToActionView));
nativeAdView.setDescriptionView(findViewById(R.id.descriptionView));
nativeAdView.setRatingView(findViewById(R.id.ratingView));
nativeAdView.setIconView(findViewById(R.id.iconView));
nativeAdView.setMediaView(findViewById(R.id.mediaView));
nativeAdView.setAdAttributionView(findViewById(R.id.adAttribution));
- When the 
NativeAdis loaded just register it for showing: 
- For single NativeAd
 - For several NativeAd instances
 
- Kotlin
 - Java
 
if (Appodeal.isLoaded(Appodeal.NATIVE)) {
  newsFeedView.registerView(Appodeal.getNativeAdCount(1))
}
if (Appodeal.isLoaded(Appodeal.NATIVE)) {
  newsFeedView.registerView(Appodeal.getNativeAdCount(1));
}
- Kotlin
 - Java
 
val needToShow = 3
if (Appodeal.getAvailableNativeAdsCount() >= needToShow) {
    val nativeAds = Appodeal.getNativeAdCount(needToShow)
    nativeAdView1.registerView(nativeAds[0])
    nativeAdView2.registerView(nativeAds[1])
    nativeAdView3.registerView(nativeAds[2])
}
int needToShow = 3;
if (Appodeal.getAvailableNativeAdsCount() >= needToShow) {
    List<NativeAd> nativeAds = Appodeal.getNativeAdCount(needToShow);
    nativeAdView1.registerView(nativeAds.get(0));
    nativeAdView2.registerView(nativeAds.get(1));
    nativeAdView3.registerView(nativeAds.get(2));
}
- When the display has been terminated and you no longer plan to use the 
NativeAdView, you should call thedestroymethod: 
- Kotlin
 - Java
 
nativeAdView.destroy()
nativeAdView.destroy();
If you want to show a new NativeAd inside used nativeAdView, just call
nativeAdView.registerView(newNativeAd) method.
Check If Ad Is Loaded
To check if at least 1 instance of NativeAd is loaded, use the method:
- Kotlin
 - Java
 
Appodeal.isLoaded(Appodeal.NATIVE)
Appodeal.isLoaded(Appodeal.NATIVE);
To get how many NativeAd instances are loaded, use the method:
- Kotlin
 - Java
 
val nativeAmount = Appodeal.getAvailableNativeAdsCount()
int nativeAmount = Appodeal.getAvailableNativeAdsCount();
By default, the Appodeal SDK with AutoCahce enabled loads 2 instances of NativeAd each
We recommend you always check whether an ad is available before trying to show it.
Get Loaded Native Ads
To get loaded native ads, use the following method:
- Kotlin
 - Java
 
val nativeAds: List<NativeAd> = Appodeal.getNativeAds(amount)
List<NativeAd> nativeAds = Appodeal.getNativeAds(int amount);
Once you get the ads, they are removed from our SDK cache.
Display
To display NativeAd, you need to call the following code:
- Kotlin
 - Java
 
NativeAdView.registerView(nativeAd: NativeAd)
NativeAdView.registerView(NativeAd nativeAd);
SDK can't show ads without a network connection!
NativeAdView.registerView() returns a boolean value indicating whether the show
method call was passed to the appropriate SDK.
Before the registerView(nativeAd) method is called, NativeAdView is in the visibility == GONE
state. After the call, the state will automatically change to visibility == VISIBLE.
You don't need to change the visibility state, Appodeal SDK does it automatically.
After calling destroy(), the state will automatically change to visibility == GONE.
NativeAdView and its successors have a built-in attribute tools:visibility="visible" so the view
will be displayed in your IDE markup during development.
Placements
Appodeal SDK allows you to tag each impression with different placement. To use placements, you need to create placements in Appodeal Dashboard. Read more about placements.
To show an ad with placement, you have to call show method:
- Kotlin
 - Java
 
NativeAdView.registerView(nativeAd: NativeAd, yourPlacementName: String)
NativeAdView.registerView(NativeAd nativeAd, String yourPlacementName)
If the loaded ad can’t be shown for a specific placement, nothing will be shown.
If auto caching is enabled, sdk will start to cache another ad, which can affect display rate. To save the loaded ad for future use (for instance, for another placement) check if the ad can be shown before calling the show method:
- Kotlin
 - Java
 
if (NativeAd.canShow(context: Context, yourPlacementName: String)) {
    NativeAdView.registerView(nativeAd: NativeAd, yourPlacementName: String)
}
if (NativeAd.canShow(Context context, String yourPlacementName)) {
    NativeAdView.registerView(NativeAd nativeAd, String yourPlacementName)
}
You can configure your impression logic for each placement.
If you have no placements, or call NativeAdView.registerView with a placement that does not exist,
the impression will be tagged with 'default' placement and its settings will be applied.
Placement settings affect ONLY ad presentation, not loading or caching.
UnregisterView
To unregister the view from displaying the currently registered native ad use the method:
- Kotlin
 - Java
 
NativeAdView.unregisterView()
NativeAdView.unregisterView();
UnregisterView method does not hide the NativeAdView. It suspends the NativeAd display
tracking.
UnregisterView makes sense to use, for example, if the NativeAdView is out of the screen while
scrolling in the list, or is temporarily overlapped by another View/Fragment/Activity
Destroy
To destroy the native ad view and perform any necessary cleanup, and hide NativeAdView use the
method:
- Kotlin
 - Java
 
NativeAdView.destroy()
NativeAdView.destroy();
This method should be called when the native ad is no longer needed.
Also, when destroy() is called, the unregisterView logic is triggered.
Callbacks
- Kotlin
 - Java
 
Appodeal.setNativeCallbacks(object : NativeCallbacks {
  override fun onNativeLoaded() {
    // Called when native ads are loaded
  }
  override fun onNativeFailedToLoad() {
    // Called when native ads are failed to load
  }
  override fun onNativeShown(nativeAd: NativeAd) {
    // Called when native ad is shown
  }
  override fun onNativeShowFailed(nativeAd: NativeAd) {
    // Called when native ad show failed
  }
  override fun onNativeClicked(nativeAd: NativeAd) {
    // Called when native ads is clicked
  }
  override fun onNativeExpired() {
    // Called when native ads is expired
  }
})
Appodeal.setNativeCallbacks(new NativeCallbacks() {
  @Override
  public void onNativeLoaded() {
    // Called when native ads are loaded
  }
  @Override
  public void onNativeFailedToLoad() {
    // Called when native ads are failed to load
  }
  @Override
  public void onNativeShown(NativeAd nativeAd) {
    // Called when native ad is shown
  }
  @Override
  public void onNativeShowFailed(NativeAd nativeAd) {
    // Called when native ad show failed
  }
  @Override
  public void onNativeClicked(NativeAd nativeAd) {
    // Called when native ads is clicked
  }
  @Override
  public void onNativeExpired() {
    // Called when native ads is expired
  }
});
All callbacks are called on the main thread.
Cache Manually
To disable automatic caching for native ads, use the code below before the SDK initialization:
- Kotlin
 - Java
 
Appodeal.setAutoCache(Appodeal.NATIVE, false)
Appodeal.setAutoCache(Appodeal.NATIVE, false);
Read more on manual caching in our ** FAQ**.
Cache
To cache native ads, use:
- Kotlin
 - Java
 
Appodeal.cache(this, Appodeal.NATIVE)
Appodeal.cache(this, Appodeal.NATIVE);
To cache multiple native ads, use:
- Kotlin
 - Java
 
Appodeal.cache(this, Appodeal.NATIVE, 3)
Appodeal.cache(this, Appodeal.NATIVE, 3);
You may request a maximum of 5 NativeAd
The number of cached ads is not guaranteed and could be less than requested.
Check If Ad Is Initialized
To check if NativeAd was initialized, you can use the method:
- Kotlin
 - Java
 
Appodeal.isInitialized(Appodeal.NATIVE)
Appodeal.isInitialized(Appodeal.NATIVE);
Returnstrue, if the NativeAd was initialized.
Check If Autocache Is Enabled
To check if autocache is enabled for NativeAd, you can use the
method:
- Kotlin
 - Java
 
Appodeal.isAutoCacheEnabled(Appodeal.NATIVE)
Appodeal.isAutoCacheEnabled(Appodeal.NATIVE);
Returns true, if autocache is enabled for native.
Get Predicted eCPM
To get the predicted eCPM from the next block in the caching queue, use the method:
- Kotlin
 - Java
 
NativeAd.predictedEcpm
NativeAd.getPredictedEcpm();
Configuration
Set preferred media content type
You can tell the Appodeal SDK your preferred content type for NativeAd. To do this, use the method:
- Kotlin
 - Java
 
// both static image and video native ads will be loaded
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Auto)
// only static image native ads will be loaded
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.NoVideo)
// only video native ads will be loaded.
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Video)
// both static image and video native ads will be loaded
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Auto);
// only static image native ads will be loaded
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.NoVideo);
// only video native ads will be loaded.
Appodeal.setPreferredNativeContentType(NativeMediaViewContentType.Video);
Setting a video type does not guarantee that it will be loaded, but only indicates the preferred type.
To check if the downloaded advertisement contains video you can use the method:
- Kotlin
 - Java
 
NativeAd.containsVideo()
NativeAd.containsVideo();
Return true if NativeAd contains video
Use the method to retrieve the preferred content type:
- Kotlin
 - Java
 
Appodeal.getPreferredNativeContentType()
Appodeal.getPreferredNativeContentType();
Only affects content inside the NativeMediaView. Therefore, it makes sense to use it only in
case of NativeAdViewContentStream template or your out custom implementation of NativeAdView.
Content for NativeIconView is always a static image
Set adChoice position
You can specify a position in one of the corners of the NativeAdView:
- XML
 - Kotlin
 - Java
 
app:adChoicePosition="end_top"
nativeAdView.setAdChoicesPosition(Position.END_TOP)
nativeAdView.setAdChoicesPosition(Position.END_TOP);
As a Position you can specify one of 4 options:
START_TOP - matches to the upper left corner of NativeAdView;
START_BOTTOM - matches to the lower left corner of NativeAdView;
END_TOP - matches the upper right corner of NativeAdView;
END_BOTTOM - matches the bottom right corner of NativeAdView.
AdAttributionView settings
You may set text color and background color for AdAttributionView in NativeAdView:
- XML
 - Kotlin
 - Java
 
app:adAttributionBackgroundColor="@color/red"
app:adAttributionTextColor="@color/black"
nativeAdView.setAdAttributionBackground(Color.RED)
nativeAdView.setAdAttributionTextColor(Color.BLACK)
nativeAdView.setAdAttributionBackground(Color.RED);
nativeAdView.setAdAttributionTextColor(Color.BLACK);
Color should have ColorInt format. See android.graphics.Color.
For custom NativeAdView, you may do the same via your xml markup using attributes android:textColor
and android:background for adAttribution TextView.
Works with lists
To use NativeAd in RecyclerView, you can use the following example:
- Create an ListItem entity that will serve to define the 
itemViewTypein RecyclerView.ListAdapter: 
- Kotlin
 - Java
 
sealed interface ListItem {
    fun getItemId(): Int
    class NativeAdItem(val getNativeAd: () -> NativeAd?) : ListItem {
        override fun getItemId() = NATIVE_AD_ITEM
        companion object {
            const val NATIVE_AD_ITEM = 3
        }
    }
    data class YourDataItem(val userData: Int) : ListItem {
        override fun getItemId() = USER_ITEM
        companion object {
            const val USER_ITEM = 2
        }
    }
}
public interface ListItem {
    int getItemId();
    int hashCode();
}
public final class NativeAdItem implements ListItem {
    private final NativeAd nativeAd;
    public NativeAdItem(NativeAd nativeAd) {
        this.nativeAd = nativeAd;
    }
    @Override
    public int getItemId() {
        return NATIVE_AD_ITEM;
    }
    public NativeAd getNativeAd() {
        return nativeAd;
    }
    public static final int NATIVE_AD_ITEM = 3;
}
public final class YourDataItem implements ListItem {
    private final int userData;
    public YourDataItem(int userData) {
        this.userData = userData;
    }
    @Override
    public int getItemId() {
        return USER_ITEM;
    }
    public int getUserData() {
        return userData;
    }
    public static final int USER_ITEM = 2;
}
- Create a 
DiffUtil.ItemCallback<ListItem>entity that will show theListAdapterthe differences between items: 
- Kotlin
 - Java
 
internal class DiffUtils : DiffUtil.ItemCallback<ListItem>() {
    override fun areItemsTheSame(oldItem: ListItem, newItem: ListItem) =
        oldItem.getItemId() == newItem.getItemId()
    override fun areContentsTheSame(oldItem: ListItem, newItem: ListItem) =
        oldItem.hashCode() == newItem.hashCode()
}
class DiffUtils extends DiffUtil.ItemCallback<ListItem> {
    @Override
    public boolean areItemsTheSame(ListItem oldItem, ListItem newItem) {
        return oldItem.getItemId() == newItem.getItemId();
    }
    @Override
    public boolean areContentsTheSame(ListItem oldItem, ListItem newItem) {
        return oldItem.hashCode() == newItem.hashCode();
    }
}
- Create a 
ListAdapterentity, which will be an adapter forRecyclerView: 
- Kotlin
 - Java
 
class NativeListAdapter : ListAdapter<ListItem, ListHolder>(DiffUtils()) {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListHolder {
        return when (viewType) {
            NATIVE_AD_ITEM -> { DynamicAdViewHolder(NativeAdViewContentStream(parent.context)) }
            else -> {
                YourViewHolder(
                    YourDataItemBinding.inflate(LayoutInflater.from(parent.context),
                                                parent,
                                                false
                    ))
            }
        }
    }
    override fun onBindViewHolder(holder: ListHolder, position: Int) {
        when (val item = getItem(position)) {
            is ListItem.YourDataItem -> (holder as YourViewHolder).bind(item)
            is ListItem.NativeAdItem -> (holder as DynamicAdViewHolder).bind(item)
        }
    }
    override fun getItemViewType(position: Int): Int {
        return when (currentList[position]) {
            is ListItem.YourDataItem -> USER_ITEM
            is ListItem.NativeAdItem -> NATIVE_AD_ITEM
        }
    }
    sealed class ListHolder(root: View) : RecyclerView.ViewHolder(root) {
        class YourViewHolder(private val binding: YourDataItemBinding) : ListHolder(binding.root) {
            fun bind(item: ListItem.YourDataItem) {
                binding.root.text = item.userData.toString()
            }
        }
        class DynamicAdViewHolder(itemView: View) : ListHolder(itemView) {
            fun bind(item: ListItem.NativeAdItem) {
                val nativeAd = item.getNativeAd.invoke()
                if (nativeAd != null) {
                    (itemView as NativeAdView).registerView(nativeAd)
                }
            }
        }
    }
}
public class NativeListAdapter extends ListAdapter<ListItem, NativeListAdapter.ListHolder> {
    public NativeListAdapter() {
        super(new DiffUtils());
    }
    @Override
    public ListHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
        if (viewType == NATIVE_AD_ITEM) {
            return new DynamicAdViewHolder(new NativeAdViewContentStream(parent.getContext()));
        } else {
            YourDataItemBinding binding = YourDataItemBinding.inflate(inflater,
                                                                      parent,
                                                                      false);
            return new YourViewHolder(binding);
        }
    }
    @Override
    public void onBindViewHolder(ListHolder holder, int position) {
        ListItem item = getItem(position);
        if (item instanceof YourDataItem) {
            ((YourViewHolder) holder).bind((YourDataItem) item);
        } else if (item instanceof NativeAdItem) {
            ((DynamicAdViewHolder) holder).bind((NativeAdItem) item);
        }
    }
    @Override
    public int getItemViewType(int position) {
        ListItem item = getItem(position);
        if (item instanceof YourDataItem) {
            return USER_ITEM;
        } else if (item instanceof NativeAdItem) {
            return NATIVE_AD_ITEM;
        }
        return super.getItemViewType(position);
    }
    abstract static class ListHolder extends RecyclerView.ViewHolder {
        ListHolder(View root) {
            super(root);
        }
    }
    static class YourViewHolder extends ListHolder {
        private YourDataItemBinding binding;
        YourViewHolder(YourDataItemBinding binding) {
            super(binding.getRoot());
            this.binding = binding;
        }
        void bind(YourDataItem item) {
            binding.getRoot().setText(String.valueOf(item.getUserData()));
        }
    }
    static class DynamicAdViewHolder extends ListHolder {
        DynamicAdViewHolder(View itemView) {
            super(itemView);
        }
        void bind(NativeAdItem item) {
            NativeAd nativeAd = item.getNativeAd();
            if (nativeAd != null) {
                ((NativeAdView) itemView).registerView(nativeAd);
            }
        }
    }
}
NATIVE_AD_ITEM - NativeAdItem.NATIVE_AD_ITEM
- As the markup of your Activity/Fragment, we use the markup
 
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:attr/colorBackground">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</FrameLayout>
We'll use the example as the markup of your YourDataItem:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp"
    android:textSize="64sp"
    tools:text="1" />
- In your 
Activity/Fragment, add the following code 
- Kotlin
 - Java
 
class NativeActivity : AppCompatActivity() {
    private val getNativeAd: () -> NativeAd? = { Appodeal.getNativeAds(1).firstOrNull() }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityNativeBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val nativeListAdapter = NativeListAdapter()
        binding.recyclerView.adapter = nativeListAdapter
        setUpAppodealSDK()
    }
    private fun setUpAppodealSDK() {
        Appodeal.setLogLevel(LogLevel.verbose)
        Appodeal.setTesting(true)
        Appodeal.initialize(this, APPODEAL_APP_KEY, Appodeal.NATIVE) { errors ->
            val initResult = if (errors.isNullOrEmpty()) "successfully" else "with ${errors.size} errors"
            Log.d("TAG", "onInitializationFinished: $initResult")
        }
    }
    private fun obtainData(nativeListAdapter: NativeListAdapter) {
        val yourDataItems = generateYourData()
        nativeListAdapter.submitList(yourDataItems.addNativeAdItems())
    }
    private fun List<ListItem>.addNativeAdItems() =
        this.foldIndexed(
            initial = listOf(),
            operation = { index: Int, acc: List<ListItem>, yourDataItem: ListItem ->
                val shouldAdd = index % STEPS == 0 && index != 0
                if (shouldAdd) {
                    acc + createNativeAdItem() + yourDataItem
                } else {
                    acc + yourDataItem
                }
            }
        )
    private fun generateYourData(): List<ListItem> =
        (1..USER_DATA_SIZE).toList().map { ListItem.YourDataItem(userData = it) }
    private fun createNativeAdItem(): ListItem.NativeAdItem =
        ListItem.NativeAdItem(getNativeAd = getNativeAd)
}
private const val USER_DATA_SIZE = 200
private const val STEPS = 5
public class NativeActivity extends AppCompatActivity {
    private static final String TAG = "NativeActivity";
    private static final String APP_KEY = "YOUR_APP_KEY";
    private static final int USER_DATA_SIZE = 200;
    private static final int STEPS = 5;
    private final GetNativeAdCallback getNativeAd = () -> {
        List<NativeAd> nativeAds = Appodeal.getNativeAds(1);
        return nativeAds.size() > 0 ? nativeAds.get(0) : null;
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityNativeBinding binding = ActivityNativeBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        NativeListAdapter nativeListAdapter = new NativeListAdapter();
        binding.recyclerView.setAdapter(nativeListAdapter);
        setUpAppodealSDK();
    }
    private void setUpAppodealSDK() {
        Appodeal.setTesting(true);
        Appodeal.initialize(this, APPODEAL_APP_KEY, Appodeal.NATIVE, errors -> {
            if (errors == null || errors.isEmpty()) {
                Log.d(TAG, "onInitializationFinished: successfully");
            } else {
                Log.d(TAG, "onInitializationFinished: with " + errors.size() + " errors");
            }
        });
    }
    private void obtainData(NativeListAdapter nativeListAdapter) {
        List<ListItem> yourDataItems = generateYourData();
        List<ListItem> itemsWithNativeAd = addNativeAdItems(yourDataItems);
        nativeListAdapter.submitList(itemsWithNativeAd);
    }
    private List<ListItem> generateYourData() {
        List<ListItem> yourDataItems = new ArrayList<>();
        for (int i = 1; i <= USER_DATA_SIZE; i++) {
            yourDataItems.add(new YourDataItem(i));
        }
        return yourDataItems;
    }
    private List<ListItem> addNativeAdItems(List<ListItem> yourDataItems) {
        List<ListItem> itemsWithNativeAd = new ArrayList<>();
        for (int i = 0; i < yourDataItems.size(); i++) {
            ListItem yourDataItem = yourDataItems.get(i);
            boolean shouldAdd = i % STEPS == 0 && i != 0;
            if (shouldAdd) {
                itemsWithNativeAd.add(createNativeAdItem());
            }
            itemsWithNativeAd.add(yourDataItem);
        }
        return itemsWithNativeAd;
    }
    private NativeAdItem createNativeAdItem() {
        return new NativeAdItem(getNativeAd.getNativeAd());
    }
    interface GetNativeAdCallback {
        NativeAd getNativeAd();
    }
}
STEPS - step through which the insertion of NativeAd will be repeated;
addNativeAdItems() - logic of inserting NativeAd into the list through a certain number of STEPS.
Done! When you want to insert native ads into RecyclerView, simply call the obtainData() method
Common Mistakes
- No adAttributionView
 
The majority of ad networks require publishers to add a special mark to a native ad, so users don’t mistake them for content. That’s why you always need to make sure, that native ads in your app have the ad attribution (e.g., “Ad”) or the AdChoices icon.
- Absence of the required native ad elements
 
Every native ad should contain:
- 
titleView TextView;
 - 
callToActionView Button;
 - 
adAttribution TextView;
 - 
NativeIconVieworNativeMedaiaView. - 
Native ad elements alteration
 
Advertisers expect that their ads will be displayed clearly and without any alteration. You can scale buttons and images, but you shouldn't crop, cover or distort them.
- Overlaying elements of native ads on each other
 
Make sure, that all elements of a native ad are visible and not overlaid.
Native ads requirements:
- All of the fields of native ad marked as mandatory must be displayed.
 - Image assets can be resized to fit your ad space but should not be significantly distorted or cropped.
 
Check Viewability
You can always check in logs if show was tracked and your ad is visible.
You will see the Native [Notify Shown] log if show was tracked successfully.
- Log
 
Appodeal  com.example.app  D Native [Notify Shown]