# Banner Cache

The banner cache is a special tool to help you integrate infeed banners more easily. It will wrap an infeed banner and use it to automatically preload banner ads aiming to have a defined amount of banners available for an immediate handout to the app whenever they are needed. Compared to using the [infeed banner](https://aatkit.gitbook.io/android-integration/formats/banner/infeed-banner) directly, it comes with the following

**Pros**

* Automatically caches banner ads, so your app can consume and present them whenever needed (i.e. when the dedicated feed cell enters the visible area of the screen)
* Automatically takes care of correct ad space counting (it counts an ad space whenever you try to consume an ad because we assume, you only consume an ad when you need to present it right now).

**Cons**

* You cannot specify specific configurations for the ad request (like e.g. keyword targeting X for the first ad request and keyword targeting Y for the next one and so on) and control the load cycle of a specific ad.

{% hint style="info" %}
We strongly recommend using the banner cache instead of the infeed banner, unless you actually need to control the ad request configuration separately per loaded ad (e.g. in very specific targeting scenarios per ad position in the feed).
{% endhint %}

### Create Banner Cache

{% tabs %}
{% tab title="Java" %}

```java
BannerCacheConfiguration configuration = new BannerCacheConfiguration("<PLACEMENT_NAME>", 3);
// Alternatively, you can use self-adjusting cache size by passing just the name:
// BannerCacheConfiguration configuration = new BannerCacheConfiguration("<PLACEMENT_NAME>");
configuration.setDelegate(this);
BannerCache bannerCache = AATKit.createBannerCache(configuration);
```

{% endtab %}

{% tab title="Kotlin" %}

<pre class="language-kotlin"><code class="lang-kotlin">val configuration = BannerCacheConfiguration("&#x3C;PLACEMENT_NAME>", 3)
// Alternatively, you can use self-adjusting cache size by passing just the name:
// val configuration = BannerCacheConfiguration("&#x3C;PLACEMENT_NAME>")
<strong>configuration.delegate = this
</strong>val bannerCache = AATKit.createBannerCache(configuration)
</code></pre>

{% endtab %}
{% endtabs %}

#### **Banner Cache Configuration**

[BannerCacheConfiguration](https://android-sdk.aatkit.com/references/-a-a-t-kit/com.intentsoftware.addapptr/-banner-cache-configuration/index.html) can be configured with the following:

* `placementName` defines the name of the internally wrapped placement (e.g. important for the statistics on the Dashboard).
* `size` defines how many preloaded banners should be available in the cache. Max value: 5.

{% hint style="info" %}
Starting with AATKit 3.15, you can skip the size parameter to let banner the cache try to automatically adjust its size.
{% endhint %}

{% hint style="info" %}
We recommend starting with a cache size of 1 and testing, if all your ad spaces get filled. If not, increase the cache size by 1 and repeat your test. The general rule should be: use the smallest possible cache size to achieve good fill rates but avoid waisting ads at the same time. Waisted ads may influence paid prices in a negative way.
{% endhint %}

* `delegate` an instance of [BannerCacheDelegate](https://android-sdk.aatkit.com/references/-a-a-t-kit/com.intentsoftware.addapptr/-banner-cache/-cache-delegate/index.html) that will notify you when the first banner is loaded and ready to be consumed.
* `requestConfiguration` an instance of [BannerRequest](https://android-sdk.aatkit.com/references/-a-a-t-kit/com.intentsoftware.addapptr/-banner-request/index.html) that will be used internally for requesting banner ads from the `InfeedBannerPlacement`.
* `retryInterval` represents the retry interval (in seconds) for failed ad load requests.
* `minimumDelay` represents the minimum delay between two banner consumptions in seconds. Useful to prevent consuming too many ads when the user is fast scrolling. Default: 1 s.
* `shouldCacheAdditionalAdAtStart` defines if the cache should load an additional ad at the beginning. `false` by default.

**Configure Banner Request**

See the [banner request configuration](https://aatkit.gitbook.io/android-integration/formats/infeed-banner#configure-aatbannerrequest) for infeed banner placement.

{% tabs %}
{% tab title="Java" %}

```java
BannerRequest request = new BannerRequest(this);
Map<String, List<String>> targeting = new HashMap<>();
targeting.put("key", Arrays.asList("value1", "value2"));
request.setTargetingInformation(targeting);
Set<BannerSize> allowedBannerSizes = new HashSet<>();
allowedBannerSizes.add(BannerSize.Banner320x53);
allowedBannerSizes.add(BannerSize.Banner300x250);
request.setBannerSizes(allowedBannerSizes);
request.setContentTargetingUrl("http://example.com/similar/content");
OR
request.setMultiContentTargetingUrls(Arrays.asList("URL1", "URL2"));
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val request = BannerRequest(this)
val targeting = mapOf("key" to listOf("value1", "value2"))
request.targetingInformation = targeting
val allowedBannerSizes = setOf(BannerSize.Banner320x53, BannerSize.Banner300x250)
request.setBannerSizes(allowedBannerSizes)
request.contentTargetingUrl = "http://example.com/similar/content"
OR
request.multiContentTargetingUrls = listOf("URL1", "URL2")
```

{% endtab %}
{% endtabs %}

### Consume Banners

To consume banners, use the `consume` method. It returns an instance of BannerPlacementLayout to be used within the app. Can return null if there are no banners available in the cache. Also automatically counts an ad space. BannerCache will no longer hold any references to returned banners, and they need to be destroyed manually by the app.

If the `force` parameter is true, the `minDelay` parameter of the [BannerCacheConfiguration](https://android-sdk.aatkit.com/references/-a-a-t-kit/com.intentsoftware.addapptr/-banner-cache-configuration/index.html) instance will be ignored.

{% tabs %}
{% tab title="Java" %}

```java
BannerPlacementLayout bannerView = bannerCache.consume();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val bannerView = bannerCache.consume()
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The ads are served from the cache using a 'first in, first out' (FIFO) approach, meaning the oldest loaded banners are displayed first.
{% endhint %}

### Destroy old banner

When you no longer need a banner, you have to destroy it manually by removing it from your view and calling the "destroy" method:

{% tabs %}
{% tab title="Java" %}

```java
[remove loadedMultiSizeBanner from your layout]
oldBanner.destroy();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
[remove loadedMultiSizeBanner from your layout]
oldBanner.destroy()
```

{% endtab %}
{% endtabs %}

### Destroy no longer needed BannerCache <a href="#markdown-header-destroy-no-longer-needed-bannercache" id="markdown-header-destroy-no-longer-needed-bannercache"></a>

For proper memory management, BannerCache needs to be destroyed when is no longer needed. The `destroy()` method destroys the BannerCache, clearing all preloaded banner ads and canceling pending reload requests.  **Destroyed BannerCache can no longer be used.**

{% tabs %}
{% tab title="Java" %}

```java
bannerCache.destroy();
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
bannerCache.destroy()
```

{% endtab %}
{% endtabs %}

### (Optional) Cache Status Delegate

To listen to the banner cache status, implement  the [`CacheStatusDelegate`](https://android-sdk.aatkit.com/references/-a-a-t-kit/com.intentsoftware.addapptr/-banner-cache/-cache-status-delegate/index.html)

{% tabs %}
{% tab title="Java" %}

```java
bannerCache.setCacheStatusDelegate(delegate);
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
bannerCache.cacheStatusDelegate = delegate
```

{% endtab %}
{% endtabs %}

### Complete Code Example

{% tabs %}
{% tab title="Java" %}

<pre class="language-java"><code class="lang-java"><strong>private BannerCache bannerCache;
</strong>
private void setUpBannerCache() {
    BannerCacheConfiguration configuration = new BannerCacheConfiguration("&#x3C;PLACEMENT_NAME>", 3);
    configuration.setDelegate(this);

    BannerRequest request = new BannerRequest(this);
    request.setContentTargetingUrl("http://example.com/similar/content");
    Map&#x3C;String, List&#x3C;String>> targeting = new HashMap&#x3C;>();
    targeting.put("key", Arrays.asList("value1", "value2"));
    request.setTargetingInformation(targeting);
    Set&#x3C;BannerSize> allowedBannerSizes = new HashSet&#x3C;>();
    allowedBannerSizes.add(BannerSize.Banner320x53);
    allowedBannerSizes.add(BannerSize.Banner300x250);
    request.setBannerSizes(allowedBannerSizes);

    configuration.setRequestConfiguration(request);

    BannerCache bannerCache = AATKit.createBannerCache(configuration);
}

@Override
protected void onResume() {
    super.onResume();
    // [IMPORTANT] Notify AATKit about activity lifecycle
    AATKit.onActivityResume(this);
}

@Override
protected void onPause() {
    // [IMPORTANT] Notify AATKit about activity lifecycle
    AATKit.onActivityPause(this);
    super.onPause();
}

@Override
protected void onDestroy() {
    bannerCache.destroy();
    super.onDestroy();
}

@Override
public void firstBannerLoaded() {
    // Get the banner view
    BannerPlacementLayout bannerView = bannerCache.consume();
    if (bannerView != null) {
        //place the loaded banner in your layout
    }
}
</code></pre>

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
private val bannerCache: BannerCache? = null

private fun setUpBannerCache() {
    val configuration = BannerCacheConfiguration("<PLACEMENT_NAME>", 3)
    configuration.delegate = this
    val request = BannerRequest(this)
    request.contentTargetingUrl = "http://example.com/similar/content"
    val targeting = mapOf("key" to listOf("value1", "value2"))
    request.targetingInformation = targeting
    val allowedBannerSizes = setOf(BannerSize.Banner320x53, BannerSize.Banner300x250)
    request.setBannerSizes(allowedBannerSizes)
    configuration.requestConfiguration = request
    val bannerCache = AATKit.createBannerCache(configuration)
}

protected override fun onResume() {
    super.onResume()
    // [IMPORTANT] Notify AATKit about activity lifecycle
    AATKit.onActivityResume(this)
}

protected override fun onPause() {
    // [IMPORTANT] Notify AATKit about activity lifecycle
    AATKit.onActivityPause(this)
    super.onPause()
}

protected override fun onDestroy() {
    bannerCache?.destroy()
    super.onDestroy()
}

override fun firstBannerLoaded() {
    // Get the banner view
    val bannerView = bannerCache?.consume()
    if (bannerView != null) {
        //place the loaded banner in your layout
    }
}
```

{% endtab %}
{% endtabs %}
