Skip to content

Instantly share code, notes, and snippets.

Avatar
💻

Aidan Follestad afollestad

💻
View GitHub Profile
View TestCollector.kt
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
package com.afollestad.flow.util
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.Unconfined
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
View IntervalFlow.kt
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@FlowPreview
@ExperimentalCoroutinesApi
fun main() {
runBlocking {
View CommandLineParser.kt
class CommandLineParser(
private val input: String
) : Iterator<String> {
private var lastIndex: Int = 0
override fun hasNext(): Boolean = lastIndex in 0..input.length - 2
override fun next(): String {
val value = StringBuilder()
var quoteStarter: Char? = null
View TypefaceHelper.kt
import android.graphics.Typeface
import androidx.annotation.CheckResult
import java.lang.Exception
/** @author Aidan Follestad (@afollestad) */
object TypefaceHelper {
private val cache = hashMapOf<String, Typeface>()
/**
* Gets a typeface by its family name. Automatically statically caches it to avoid
@afollestad
afollestad / Debouncer.kt
Created Jun 12, 2019
Debounce clicks in Kotlin
View Debouncer.kt
import android.view.View
internal object Debouncer {
@Volatile private var enabled: Boolean = true
private val enableAgain = Runnable { enabled = true }
fun canPerform(view: View): Boolean {
if (enabled) {
enabled = false
view.post(enableAgain)
@afollestad
afollestad / gist:e1ada7b0c1d3a390e4b97910846cba69
Created Apr 19, 2019
List of components that can be installed on Travis.ci
View gist:e1ada7b0c1d3a390e4b97910846cba69
addon-google_apis-google-10
addon-google_apis-google-11
addon-google_apis-google-12
addon-google_apis-google-13
addon-google_apis-google-14
addon-google_apis-google-15
addon-google_apis-google-16
addon-google_apis-google-17
addon-google_apis-google-18
addon-google_apis-google-19
View TextChangedExtension.kt
import android.text.Editable
import android.text.TextWatcher
import android.widget.EditText
fun EditText.onTextChanged(
@IntRange(from = 0, to = 10000) debounce: Int = 0,
cb: (String) -> Unit
) {
addTextChangedListener(object : TextWatcher {
val callbackRunner = Runnable {
@afollestad
afollestad / LifecycleAwareDisposable.kt
Created Dec 14, 2018
Make an Observable Lifecycle aware - disposing itself when the lifecycle stops
View LifecycleAwareDisposable.kt
/** @author Aidan Follestad (afollestad) */
class LifecycleAwareDisposable(
private val disposable: Disposable
) : LifecycleObserver {
@OnLifecycleEvent(ON_DESTROY)
fun dispose() = disposable.dispose()
}
/** @author Aidan Follestad (afollestad) */
@afollestad
afollestad / LivedataMap.kt
Created Dec 14, 2018
Map and switchMap live data with extension functions instead of method calls.
View LivedataMap.kt
import androidx.lifecycle.LiveData
import androidx.lifecycle.Transformations
fun <X, Y> LiveData<X>.map(mapper: (X) -> Y) =
Transformations.map(this, mapper)!!
fun <X, Y> LiveData<X>.switchMap(mapper: (X) -> LiveData<Y>) =
Transformations.switchMap(this, mapper)!!
@afollestad
afollestad / ViewLifecycleOwner.kt
Created Dec 14, 2018
Create a lifecycle owner for a view without any boiler plate
View ViewLifecycleOwner.kt
import android.view.View
import android.view.View.OnAttachStateChangeListener
import androidx.lifecycle.LifecycleOwner
/** @author Aidan Follestad (@afollestad) */
class ViewLifecycleOwner(view: View) : LifecycleOwner, OnAttachStateChangeListener {
private val lifecycle = SimpleLifecycle(this)
init {