Kulwinder Singh
07/31/2019, 6:51 AMdelay
execution for random time between 5-9 mins,
So what is best way to do it with kotlin in android ? Simply using delay
or flows/channels
?gildor
07/31/2019, 6:53 AMKulwinder Singh
07/31/2019, 6:55 AMthevery
07/31/2019, 10:42 AMgildor
07/31/2019, 11:35 AMgildor
07/31/2019, 11:39 AMKulwinder Singh
07/31/2019, 1:57 PMboolean
like isDelayCompleted = true
value to tell that delay is completed
3. then on any user event occurrence(ie: button click, swipe etc) then i want to check if that isDelayCompleted
is true
, so if it true then i will show ad and also again repeat from step 1-3 else if false do nothing
So here if you note i don't have to start next delay immediately after first finish but i have to wait to consume or use value produced by first delay and then start another delay, so that's why i'm thinking if Flow/Channel can help me here. i have very good experience in coroutines but did not worked with channels so that's why i don't know if it will help in this casegildor
07/31/2019, 2:36 PMPablichjenkov
07/31/2019, 6:33 PMthevery
07/31/2019, 6:34 PMPablichjenkov
07/31/2019, 6:38 PMgildor
07/31/2019, 11:26 PMvinay
08/01/2019, 2:22 AMJag
08/01/2019, 2:27 AMactionsFlow.zipWithDefault(adsFlow, AdsOperation.WaitForAd) { action, adOperation ->
when (adOperation) {
AdsOperation.ShowAd -> "$action: show ad"
AdsOperation.WaitForAd -> "$action: wait for ad"
}
}.collect { println(it) }
zipWithDefault
is a slight modification to the existing zip operation which just emits the default when nothing is available for emission from the second flow
.
The ads flow is very easy:
fun adsFlow(duration: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) = flow {
while (true) {
delay(unit.toMillis(duration))
emit(AdsOperation.ShowAd)
}
}
But I’d go with Andrey’s approach if it works for you 🙂Kulwinder Singh
08/02/2019, 9:16 AMclass AdFreeMethod1(lifecycleScope: LifecycleCoroutineScope) : AdFreeCalls {
companion object {
private const val MAX_ADS_PER_SESSION = 10
}
private var adsToShow = 0
init {
lifecycleScope.launch {
for (i in 0..MAX_ADS_PER_SESSION) {
val delayTime = (4.minute..7.minute).random()
delay(delayTime)
adsToShow += 1
}
}
}
override fun isAdFreeCall(): Boolean {
val isAdFreeCall = adsToShow == 0
if (adsToShow != 0) {
adsToShow -= 1
}
return isAdFreeCall
}
private val Int.minute: Long
get() = this * 60000L
}
gildor
08/02/2019, 9:18 AMadsToShow
on isAdFreeCall()
by comparing current system time with last system timegildor
08/02/2019, 9:25 AMclass AdFreeMethod(
private val minDelaySec: Long,
private val maxDelaySec: Long,
private val maxAdsPerSession: Long = 10,
initialAdsToShow: Long = 0L
) : AdFreeCalls {
private var showedAds = 0
private var adsToShow = initialAdsToShow
private var lastUpdateTime = System.currentTimeMillis()
override fun isAdFreeCall(): Boolean {
if (showedAds >= maxAdsPerSession) return true
val oldUpdateTime = lastUpdateTime
lastUpdateTime = System.currentTimeMillis()
val timeFromLastRequest = lastUpdateTime - oldUpdateTime
// Semantics a bit different, only 1 random,
// you can just change this code to get random intervals for each period
adsToShow += timeFromLastRequest / Random.nextLong(minDelaySec, maxDelaySec)
// -1 from amount of free calls for this call
adsToShow--
adsToShow = adsToShow.coerceAtLeast(0)
val adFreeCall = adsToShow == 0L
if (!adFreeCall) {
showedAds++
}
return adFreeCall
}
}
Kulwinder Singh
08/02/2019, 9:38 AMgildor
08/02/2019, 9:56 AMKulwinder Singh
08/03/2019, 4:53 AMadsToShow
because i had created those only for coroutines. so here is final version i'm using
class AdFreeMethod(
private val minDelayMillis: Long = 4.minuteToMillis,
private val maxDelayMillis: Long = 7.minuteToMillis,
private val maxAdsPerSession: Long = 10
) : AdFreeCalls {
private var showedAds = 0
private var lastAdTime = System.currentTimeMillis()
private var nextAdTime = lastAdTime + getNextDelay()
override fun isAdFreeCall(): Boolean {
if (showedAds >= maxAdsPerSession) return true
val currentTime = System.currentTimeMillis()
return if (currentTime >= nextAdTime) {
showedAds++
nextAdTime = currentTime + getNextDelay()
lastAdTime = currentTime
false
} else true
}
private fun getNextDelay() = Random.nextLong(minDelayMillis, maxDelayMillis)
}
gildor
08/03/2019, 5:46 AMKulwinder Singh
08/03/2019, 5:51 AMadFreeCalls
only for coroutines, because in coroutine after one delay instantly i have to start next delay and therefore i want to keep record of number of delays. but now with current logic i don't need that