Skip to content

Instantly share code, notes, and snippets.

Avatar

Zak Taccardi ZakTaccardi

View GitHub Profile
@ZakTaccardi
ZakTaccardi / LibsAccessor.kt
Created Aug 29, 2022
Migrate to version catalogs now!
View LibsAccessor.kt
import myapp.dependencyCatalogs.LibsCatalogExtension
import org.gradle.api.Project
import org.gradle.kotlin.dsl.the
// this file is in `buildSrc` in the root package, so `libs` will point to this function or the generated `libs` from the `.toml` file
/**
* Wrapper with no package name to have projects automatically pick up [LibsCatalogExtension] when this function exists.
*
* The generated version accessors is [org.gradle.accessors.dm.LibrariesForLibs].
@ZakTaccardi
ZakTaccardi / LocalPropertySupport.kt
Created Jan 3, 2022
`local.properties` and project level gradle properties support for Configuration Cache
View LocalPropertySupport.kt
import org.gradle.api.Project
import org.gradle.api.file.ProjectLayout
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.provider.ProviderFactory
import org.gradle.api.provider.ValueSource
import org.gradle.api.provider.ValueSourceParameters
import org.gradle.kotlin.dsl.of
import java.io.StringReader
import java.util.Properties
@ZakTaccardi
ZakTaccardi / FunctionInterceptionExample.kt
Created Dec 16, 2020
Function Interception (composition)
View FunctionInterceptionExample.kt
/**
* An abstraction around a 3rd party SDK that does some magic to
* identify if a user is a bot or not.
*
* The real implementation may have direct Android dependencies,
* so being able to swap this out is useful for unit testing
*/
interface VendorSdk {
suspend fun isUserABot(): Boolean
}
@ZakTaccardi
ZakTaccardi / SimpleMvi.kt
Last active May 22, 2020
Simple MVI coroutine example
View SimpleMvi.kt
interface MviViewModel<in I, out VS, out SE> {
val states: Flow<VS>
val sideEffects: Flow<SE>
fun send(intention: I)
}
class SimpleViewModel(scope: CoroutineScope) : MviViewModel<Intention, State, SideEffect> {
private val _states = MutableStateFlow(0) // this is an always have an initial state example
private val _sideEffects = Channel<SideEffect>(capacity = Channel.UNLIMITED) // we don't want the actor coroutine to ever suspend, in case there is no UI consuming
@ZakTaccardi
ZakTaccardi / 1-ManualFragment.kt
Created May 20, 2020
A practical example on why Composition over Inheritance matters for your codebase
View 1-ManualFragment.kt
/**
* Solution 1 = Manual
*/
internal class MyManualFragment(
private val viewModel: ViewModel
) : Fragment() {
private var startedScope: CoroutineScope? = null
override fun onStart() {
View LifecycleScopeExtensionsInternal.kt
import androidx.fragment.app.Fragment
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.CoroutineScope
@Suppress("UNCHECKED_CAST")
internal class ViewLifecycleScopeImpl(
private val fragment: Fragment
) : ViewLifecycleScope {
View NoInitialStateFlow.kt
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
/**
* A variant of [StateFlow] that allows an initial state
*/
interface NoInitialStateFlow<T> : Flow<T> {
/**
View StateActor.kt
import kotlinx.coroutines.CompletionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.channels.SendChannel
import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.flow.Flow
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
interface StateActor<S, I> : SendChannel<I> {
View DontBreakTheChainTest.kt
package com.capitalone.android.coroutines
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
import kotlinx.coroutines.runBlocking
import org.junit.Test
import kotlin.coroutines.ContinuationInterceptor
@ZakTaccardi
ZakTaccardi / CoroutineScope.md
Created Apr 22, 2020
Don't break the chain
View CoroutineScope.md

PSA, don’t construct new CoroutineScopes and break structured concurrency in your classes.

class TransactionsDb(dispatchers: MyDispatchers) {
  private val scope = CoroutineScope(dispatchers.io)
}

This can cause tests to pass when an exception is thrown.