Skip to content

Instantly share code, notes, and snippets.

View ZakTaccardi's full-sized avatar

Zak Taccardi ZakTaccardi

View GitHub Profile
@ZakTaccardi
ZakTaccardi / LibsAccessor.kt
Created August 29, 2022 17:09
Migrate to version catalogs now!
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 January 3, 2022 16:48
`local.properties` and project level gradle properties support for Configuration Cache
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 December 16, 2020 17:15
Function Interception (composition)
/**
* 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 16:12
Simple MVI coroutine example
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 17:22
A practical example on why Composition over Inheritance matters for your codebase
/**
* Solution 1 = Manual
*/
internal class MyManualFragment(
private val viewModel: ViewModel
) : Fragment() {
private var startedScope: CoroutineScope? = null
override fun onStart() {
@ZakTaccardi
ZakTaccardi / LifecycleScopeExtensionsInternal.kt
Created May 18, 2020 15:54
ViewLifecycleScope extensions
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 {
@ZakTaccardi
ZakTaccardi / NoInitialStateFlow.kt
Created May 9, 2020 01:26
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> {
/**
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> {
@ZakTaccardi
ZakTaccardi / DontBreakTheChainTest.kt
Last active May 7, 2020 19:56
Don't break the chain
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 April 22, 2020 20:52
Don't break the chain

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.