Skip to content

Instantly share code, notes, and snippets.

View psteiger's full-sized avatar
🎯
Focusing

Patrick Steiger psteiger

🎯
Focusing
View GitHub Profile
@psteiger
psteiger / CoroutineMonitoring.kt
Last active April 13, 2023 00:27
Short example of how continuation duration differs from coroutine duration.
import kotlinx.coroutines.*
import kotlin.coroutines.*
import kotlin.system.*
/** Wraps original dispatcher, so we can wrap the continuations. */
class Monitor(
private val interceptor: ContinuationInterceptor
) : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
interceptor.interceptContinuation(MeasuredContinuation(continuation))
@psteiger
psteiger / AccumulatingFlow.kt
Last active April 8, 2023 21:39
Accumulating Kotlin Flow
/**
* Gates upstream flow emissions by [passThrough].
*
* When upstream flow emits a value, either emits the value downstream if the last value emitted by [passThrough]
* was `true`, or accumulates it for later emission if `false`. Accumulated values are emitted once [passThrough]
* emits `true`.
*/
@OptIn(FlowPreview::class) // produceIn is stable since kotlinx-coroutines 1.7.0-Beta
internal fun <T> Flow<T>.accumulateBy(passThrough: Flow<Boolean>) = flow<List<T>> {
@psteiger
psteiger / Biller.kt
Last active November 20, 2020 18:01
BillingClient wrapper with Coroutines and SharedFlow
@Singleton
class Biller @Inject constructor(
@ApplicationContext private val context: Context,
) : PurchasesUpdatedListener, BillingClientStateListener {
private var billingClient: BillingClient =
BillingClient.newBuilder(context)
.setListener(this)
.enablePendingPurchases()
.build()
@AndroidEntryPoint
class NearbyUsersActivity : AppCompatActivity() {
private val viewModel: NearbyUsersViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
viewModel
.locations
.onEach { /* new locations received */ }
.observeIn(this)
@PublishedApi
internal class ObserverImpl<T> (
lifecycleOwner: LifecycleOwner,
private val flow: Flow<T>,
private val collector: suspend (T) -> Unit
) : DefaultLifecycleObserver {
private var job: Job? = null
override fun onStart(owner: LifecycleOwner) {
@Singleton
class NearbyUsersDataSource @Inject constructor() {
// Ideally, those should be constructor-injected.
val geoFire = GeoFire(FirebaseDatabase.getInstance().getReference("geofire"))
val geoLocation = GeoLocation(0.0, 0.0)
val radius = 100.0
val geoQuery = geoFire.queryAtLocation(geoLocation, radius)
private fun GeoQuery.asFlow() = callbackFlow {
@AndroidEntryPoint
class NearbyUsersActivity : AppCompatActivity() {
private val viewModel: NearbyUsersViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
lifecycleScope.launchWhenStarted {
viewModel.locations.collect {
// Update views with the data.
}
@Singleton
class NearbyUsersDataSource @Inject constructor() {
// Ideally, those should be constructor-injected.
val geoFire = GeoFire(FirebaseDatabase.getInstance().getReference("geofire"))
val geoLocation = GeoLocation(0.0, 0.0)
val radius = 100.0
val geoQuery = geoFire.queryAtLocation(geoLocation, radius)
private fun GeoQuery.asFlow() = callbackFlow {
@AndroidEntryPoint
class NearbyUsersActivity : AppCompatActivity() {
private val viewModel: NearbyUsersViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
viewModel.locations.observe(this) { state: State ->
// Update views with the data.
}
}
class NearbyUsersViewModel @ViewModelInject constructor(
nearbyUsersRepository: NearbyUsersRepository
) : ViewModel() {
val locations get() = nearbyUsersRepository.locations
}