Skip to content

Instantly share code, notes, and snippets.

View yongjhih's full-sized avatar
🏠
Working from home

Andrew Chen yongjhih

🏠
Working from home
View GitHub Profile
@yongjhih
yongjhih / MemoizedInterceptor.kt
Last active August 17, 2023 15:16
Memoized Cache Interceptor
/**
* Intercepts and caches memoized responses based on the provided LruCache.
*
* @property cache an instance of LruCache to store the responses.
*/
class MemoizedInterceptor(private val cache: LruCache<String, Response>) : Interceptor {
/**
* Callback that will be invoked when a cached response is found.
* @param request the request being executed.
* @param isFresh `true` if the cached response is still fresh, `false` otherwise.
class SimpleLifecycleObserver(
var onCreate: SimpleLifecycleObserver.(LifecycleOwner) -> Unit = {},
var onStart: SimpleLifecycleObserver.(LifecycleOwner) -> Unit = {},
var onResume: SimpleLifecycleObserver.(LifecycleOwner) -> Unit = {},
var onPause: SimpleLifecycleObserver.(LifecycleOwner) -> Unit = {},
var onStop: SimpleLifecycleObserver.(LifecycleOwner) -> Unit = {},
var onDestroy: SimpleLifecycleObserver.(LifecycleOwner) -> Unit = {},
) : DefaultLifecycleObserver {
fun onCreate(onCreate: SimpleLifecycleObserver.(LifecycleOwner) -> Unit) = apply {
this.onCreate = onCreate
fun <I> ActivityResultCaller.registerForActivityResult(
onCreateIntent: Context.(input: I) -> Intent,
callback: ActivityResultCallback<Pair<Int, Intent?>>,
) = registerForActivityResult(
activityResultContract(onCreateIntent),
callback,
)
/**
* ```
@Preview
@Composable
fun EllipsisTextPreview(
) {
EllipsisText(
text = "This is a very long text that should This is a very long text that should This is a very long text that should bbbThis is a very long text that should be truncated",
maxLines = 2,
)
}
@Composable
fun EllipseText(
text: String,
modifier: Modifier = Modifier,
style: TextStyle = LocalTextStyle.current,
fontStyle: FontStyle? = null,
maxLines: Int = Int.MAX_VALUE,
onMoreText: Context.() -> String = { "... Show More" },
moreTextStyle: SpanStyle = SpanStyle(fontWeight = FontWeight.W500),
textAlign: TextAlign? = null
fun <T: View> T.focuses(): Flow<Pair<T, Boolean>> = callbackFlow {
val oldListener = onFocusChangeListener
val listener = View.OnFocusChangeListener { v, hasFocus ->
oldListener?.onFocusChange(v, hasFocus)
@Suppress("UNCHECKED_CAST")
trySend(v as T to hasFocus)
}
onFocusChangeListener = listener
awaitClose { onFocusChangeListener = oldListener }
}
fun <T> Sequence<T>.until(predicate: (T) -> Boolean) = sequence {
for (it in this@until) {
if (predicate(it)) break
yield(it)
}
}
fun <T> Sequence<T>.untilInclusive(predicate: (T) -> Boolean) = sequence {
for (it in this@untilInclusive) {
yield(it)
fun CharSequence.indicesOf(pattern: String): Sequence<Int> = sequence {
var startIndex = 0
while (true) {
startIndex = indexOf(pattern, startIndex)
if (startIndex < 0) break
yield(startIndex)
startIndex += pattern.length
}
}
@OptIn(ExperimentalContracts::class)
fun <T: () -> R, R> T.measureTimeMillis(test: Boolean = true, onMeasure: (Long) -> Unit): R {
contract {
callsInPlace(this@measureTimeMillis, InvocationKind.EXACTLY_ONCE)
}
if (!test) return this()
val start = System.currentTimeMillis()
val res = this()
onMeasure(System.currentTimeMillis() - start)
class Solution {
val cache: MutableMap<Int, Int> = mutableMapOf()
fun climbStairs(n: Int): Int {
if (n <= 0) return 0
if (n == 1) return 1
if (n == 2) return 2
if (cache[n] != null) return cache[n]!!
val res = climbStairs(n-1) + climbStairs(n-2)
cache[n] = res