Skip to content

Instantly share code, notes, and snippets.

View gmk57's full-sized avatar

George Kropotkin gmk57

View GitHub Profile
@gmk57
gmk57 / ResultFlatMap.kt
Created May 21, 2022 14:11
Implementation of Result.flatMap(), missing from Kotlin stdlib
inline fun <R, T> Result<T>.flatMap(transform: (T) -> Result<R>): Result<R> =
fold({ transform(it) }, { Result.failure(it) })
fun main() {
getUserInput()
.flatMap { input -> parseInput(input) }
.flatMap { numbers -> calculateMax(numbers) }
.onSuccess { maxNumber -> println("max: $maxNumber") }
.onFailure { throwable -> throwable.printStackTrace() }
}
@gmk57
gmk57 / CoroutineTimer.kt
Last active April 18, 2024 14:38
Coroutine-based solution for delayed and periodic work
/**
* Coroutine-based solution for delayed and periodic work. May fire once (if [interval] omitted)
* or periodically ([startDelay] defaults to [interval] in this case), replacing both
* `Observable.timer()` & `Observable.interval()` from RxJava.
*
* In contrast to RxJava, intervals are calculated since previous run completion; this is more
* convenient for potentially long work (prevents overlapping) and does not suffer from queueing
* multiple invocations in Doze mode on Android.
*
* Dispatcher is inherited from scope, may be overridden via [context] parameter.
@gmk57
gmk57 / Sending events to UI.kt
Last active February 13, 2024 15:17
Sending events to UI with Channel/Flow + custom collector (see my first comment for reasons behind it)
/**
* Starts collecting a flow when the lifecycle is started, and **cancels** the collection on stop.
* This is different from `lifecycleScope.launchWhenStarted { flow.collect{...} }`, in which case
* the coroutine is just suspended on stop.
*/
inline fun <reified T> Flow<T>.collectWhileStarted(
lifecycleOwner: LifecycleOwner,
noinline action: suspend (T) -> Unit
) {
object : DefaultLifecycleObserver {
@gmk57
gmk57 / MainActivity.kt
Last active September 19, 2023 15:43
Testing various ways to put line breaks in Android XML resources
private const val TAG = "MainActivity"
class MainActivity : AppCompatActivity(R.layout.activity_main) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
getString(R.string.str10).let {
Log.i(TAG, "str '${it.replace("\n", "\\n")}', raw '$it'")
findViewById<TextView>(R.id.text).apply {
text = it
@gmk57
gmk57 / 1 ViewBindingDelegates.kt
Last active January 25, 2024 09:01
Kotlin delegates for Android View Binding with usage examples
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.viewbinding.ViewBinding
@gmk57
gmk57 / RunRetrying.kt
Last active December 6, 2022 19:23
Coroutine-based solution for retries with delay
/**
* Analogue of [runCatching] with retry, delay & logging added.
* Re-throws CancellationException to avoid the need to explicitly skip it in [onFailure].
* Intervals are calculated since previous failure.
*/
@ExperimentalTime
suspend fun <T> runRetrying(
times: Int,
interval: Duration,
name: String,