100 Kotlin Tricks for Android¶
Each trick includes a short why, code, and an Android-flavored use case.
1. Safe Trim Extension¶
- Explanation: Avoids NPE while cleaning text input.
- Code:
- Use case: Sanitizing EditText input before validation.
- Why it matters: Removes boilerplate null checks and improves readability.
2. Int.dp to Px¶
- Explanation: Quick density conversion.
- Code:
- Use case: Building custom views without Context.
- Why it matters: Keeps layout math concise.
3. Px to Dp Extension¶
- Explanation: Reverse conversion for measuring runtime sizes.
- Code:
- Use case: Logging sizes for UI debugging.
- Why it matters: Prevents magic numbers and mis-scaled UI.
4. Nullable Boolean orFalse¶
- Explanation: Collapse nullable booleans safely.
- Code:
- Use case: Feature flags fetched from remote config.
- Why it matters: Avoids double-bang (!!) crashes.
5. ifTrue Inline¶
- Explanation: Execute block only when condition true.
- Code:
- Use case: Toggle debug overlays.
- Why it matters: Improves intent and reduces nesting.
6. String.takeIfNotBlank¶
- Explanation: Keep non-blank strings else null.
- Code:
- Use case: Optional form fields.
- Why it matters: Cleaner nullable handling.
7. requireNotNullWithMessage¶
- Explanation: Inline require with lazy message.
- Code:
- Use case: Constructor preconditions.
- Why it matters: Lazy messages avoid string building cost.
8. checkNotNullLog¶
- Explanation: Check and log before throwing.
- Code:
- Use case: Defensive coding in repository layer.
- Why it matters: Keeps crash clues.
9. buildString DSL¶
- Explanation: Idiomatic string builder.
- Code:
- Use case: Composing snack bar messages.
- Why it matters: Faster than string concatenation in loops.
10. runCatchingMap¶
- Explanation: Map Result success without re-wrapping.
- Code:
- Use case: Repository transformations.
- Why it matters: Keeps Result chain pure.
11. retrySuspend¶
- Explanation: Suspends with retries and delay.
- Code:
- Use case: Retrying network calls.
- Why it matters: Simple exponential-ish backoff.
12. coroutineLaunchIO¶
- Explanation: Shortcut for IO dispatcher launch.
- Code:
- Use case: Repository disk operations.
- Why it matters: Reduces verbosity and mistakes.
13. withMain¶
- Explanation: Switch to Main dispatcher inline.
- Code:
- Use case: Updating UI after background work.
- Why it matters: Prevents thread violations.
14. parallelMap¶
- Explanation: Run collection operations concurrently.
- Code:
- Use case: Fetching multiple endpoints.
- Why it matters: Utilizes concurrency safely.
15. debounce Flow Extension¶
- Explanation: Debounce with default dispatcher.
- Code:
- Use case: Search box requests.
- Why it matters: Saves bandwidth and CPU.
16. throttleFirst Flow¶
- Explanation: Emit first then silence window.
- Code:
- Use case: Button spam prevention.
- Why it matters: Prevents duplicate actions.
17. distinctUntilChangedByKey¶
- Explanation: Skip repeats by selector.
- Code:
- Use case: UI state updates by id.
- Why it matters: Cuts recompositions.
18. shareWhileSubscribed¶
- Explanation: Share flow only when active.
- Code:
- Use case: ViewModel data streams.
- Why it matters: Saves work when no observers.
19. stateInDefault¶
- Explanation: Convert to StateFlow with default.
- Code:
- Use case: Exposing UI state.
- Why it matters: Ensures initial value and cancellation awareness.
20. Flow retryWithBackoff¶
- Explanation: Operator with exponential backoff.
- Code:
- Use case: Streaming network data.
- Why it matters: More resilient flows.
21. Sealed UiState¶
- Explanation: Single source for UI render states.
- Code:
- Use case: ViewModel exposures.
- Why it matters: Exhaustive when rendering.
22. Sealed Intent¶
- Explanation: Model user intents as sealed types.
- Code:
- Use case: MVI architectures.
- Why it matters: Compiler checks for new actions.
23. Data class copy with defaults helper¶
- Explanation: Provide safe copy with optional params.
- Code:
- Use case: Reducers.
- Why it matters: Avoids repeating property list.
24. Inline class for ids¶
- Explanation: Type-safe ids without runtime cost.
- Code:
- Use case: Distinguish different Long ids.
- Why it matters: Prevents parameter mixups.
25. Delegated preference¶
- Explanation: Custom delegate to SharedPreferences.
- Code:
class PrefDelegate<T>(private val prefs: SharedPreferences, private val key: String, private val default: T) { operator fun getValue(thisRef: Any?, property: KProperty<*>) = when(default){ is Int -> prefs.getInt(key, default) as T is Boolean -> prefs.getBoolean(key, default) as T else -> prefs.getString(key, default as? String) as T } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { with(prefs.edit()) { when(value){ is Int -> putInt(key, value) is Boolean -> putBoolean(key, value) is String -> putString(key, value) } }.apply() } } - Use case: ViewModel config flags.
- Why it matters: Removes preference boilerplate.
26. lazyNonThreadSafe¶
- Explanation: Faster lazy when single-threaded.
- Code:
- Use case: Fragment properties.
- Why it matters: Avoids synchronization overhead.
27. observableState¶
- Explanation: Observe property changes.
- Code:
- Use case: Search UI updates.
- Why it matters: Simplifies listener wiring.
28. vetoableRange¶
- Explanation: Prevent invalid assignment.
- Code:
- Use case: Settings sliders.
- Why it matters: Guards invariants.
29. by map delegate¶
- Explanation: Map-backed model initialization.
- Code:
- Use case: Parsing JSON to model quickly.
- Why it matters: Removes manual assignments.
30. Kotlin DSL builder¶
- Explanation: Simple DSL via lambdas with receiver.
- Code:
- Use case: Building Retrofit requests in tests.
- Why it matters: Declarative and readable.
31. inline measureDuration¶
- Explanation: Time any block.
- Code:
- Use case: Profiling slow UI code.
- Why it matters: Lightweight instrumentation.
32. nonEmptyListOf¶
- Explanation: Enforce non-empty collections at creation.
- Code:
- Use case: Adapter data needing at least one item.
- Why it matters: Avoids empty state crashes.
33. runIf¶
- Explanation: Inline conditional execution with return value.
- Code:
- Use case: Add headers only when logged in.
- Why it matters: Keeps pipelines fluent.
34. takeUnlessNullOrEmpty¶
- Explanation: Keep list unless empty.
- Code:
- Use case: Optional sections in Compose.
- Why it matters: Avoids redundant branches.
35. stringBuilderUse¶
- Explanation: Use
usewith StringWriter for IO safety. - Code:
- Use case: Asset file loading.
- Why it matters: Closes streams automatically.
36. suspendRunCatching¶
- Explanation: Suspend-aware Result wrapper.
- Code:
- Use case: Repository network calls.
- Why it matters: Consistent error pipeline.
37. combineLatest3¶
- Explanation: Combine three flows succinctly.
- Code:
- Use case: UI state from multiple sources.
- Why it matters: Avoid nested combines.
38. MutableStateFlow.update¶
- Explanation: Atomic update helper.
- Code:
- Use case: Reducers in ViewModel.
- Why it matters: Less ceremony than emit.
39. SharedFlow emitLatest¶
- Explanation: Drop buffer and emit latest.
- Code:
- Use case: Navigation events.
- Why it matters: Avoids lost emissions.
40. inline crossinline builder¶
- Explanation: Prevent non-local returns in DSL.
- Code:
- Use case: Callback-based APIs.
- Why it matters: Safer control flow.
41. reified cast¶
- Explanation: Type-safe cast without class token.
- Code:
- Use case: Parsing bundle extras.
- Why it matters: Eliminates Class
plumbing.
42. reified Gson¶
- Explanation: Generic JSON decode.
- Code:
- Use case: Cache decoding.
- Why it matters: One-liner decode.
43. reified ViewModel lookup¶
- Explanation: Simplify ViewModel retrieval.
- Code:
- Use case: Fragment scoped VMs.
- Why it matters: Removes factory boilerplate.
44. fragmentArgs delegate¶
- Explanation: Property delegate for fragment args.
- Code:
- Use case: Passing small payloads.
- Why it matters: Safer than manual casts.
45. weak reference callback¶
- Explanation: Prevent leaks for listeners.
- Code:
- Use case: Long-lived managers holding Activity callbacks.
- Why it matters: Avoids memory leaks.
46. inline onApi¶
- Explanation: Run code only on min API.
- Code:
- Use case: Feature gating.
- Why it matters: Keeps compatibility checks tidy.
47. enumSafeValueOf¶
- Explanation: Safe enum parsing.
- Code:
- Use case: Parsing remote enum strings.
- Why it matters: Avoids exceptions.
48. BigDecimal.exactOrNull¶
- Explanation: Convert string to BigDecimal safely.
- Code:
- Use case: Price inputs.
- Why it matters: Prevents crashes on invalid numbers.
49. Guard clause function¶
- Explanation: Early return helper.
- Code:
- Use case: Validation chains.
- Why it matters: Reduces nesting.
50. requireMainThread¶
- Explanation: Enforce main thread execution.
- Code:
- Use case: UI operations.
- Why it matters: Catches threading bugs.
51. LazyFlow¶
- Explanation: Create flow that runs on first collect.
- Code:
- Use case: Deferred expensive fetch.
- Why it matters: Avoids work until needed.
52. Flow catchMap¶
- Explanation: Map errors to state objects.
- Code:
- Use case: Emit empty on error for UI.
- Why it matters: Prevents cancellations.
53. flowOnBoundary¶
- Explanation: Split upstream/downstream dispatchers.
- Code:
- Use case: Network then UI mapping.
- Why it matters: Correct dispatcher usage.
54. rememberCoroutineScope in Compose¶
- Explanation: Launch coroutines scoped to composition.
- Code:
- Use case: Fire-and-forget actions.
- Why it matters: Avoids leaking jobs.
55. derivedStateOf for expensive calcs¶
- Explanation: Memoize derived state.
- Code:
- Use case: Filtering lists in Compose.
- Why it matters: Cuts recomposition cost.
56. snapshotFlow bridging¶
- Explanation: Convert Compose state to Flow.
- Code:
- Use case: Paging analytics.
- Why it matters: Observes UI state reactively.
57. LaunchedEffect with keys¶
- Explanation: Restart effect when key changes.
- Code:
- Use case: Detail screens.
- Why it matters: Avoids stale jobs.
58. rememberSaveable state holder¶
- Explanation: Save state across process death.
- Code:
- Use case: Form fields.
- Why it matters: Survives recreation.
59. MutableStateFlow.asStateFlow¶
- Explanation: Expose read-only view.
- Code:
- Use case: ViewModel encapsulation.
- Why it matters: Prevents external mutation.
60. combineLatestList¶
- Explanation: Combine dynamic list of flows.
- Code:
- Use case: Aggregating multiple sources.
- Why it matters: Scales with inputs.
61. Mutex protect¶
- Explanation: Protect critical section in coroutines.
- Code:
- Use case: Cache writes.
- Why it matters: Avoids races without threads.
62. Channel conflated sendLatest¶
- Explanation: Conflate channel to keep last value.
- Code:
- Use case: Progress updates.
- Why it matters: Drops redundant work.
63. CallbackFlow adapter¶
- Explanation: Bridge callback APIs to Flow.
- Code:
- Use case: Location updates.
- Why it matters: Structured cancellation.
64. suspendCancellableCoroutine¶
- Explanation: Wrap async callback with cancellation.
- Code:
- Use case: Firebase Tasks.
- Why it matters: Proper coroutine interop.
65. Flow buffer tuning¶
- Explanation: Add buffer to prevent backpressure.
- Code:
- Use case: Sensor streams.
- Why it matters: Avoids missed samples.
66. sealed Result with domain errors¶
- Explanation: Domain-specific error channel.
- Code:
- Use case: UI error handling.
- Why it matters: More expressive than Boolean flags.
67. inline contract for returns¶
- Explanation: Improve smart casting.
- Code:
- Use case: Validation helpers.
- Why it matters: Cleaner smart casts.
68. sequence for laziness¶
- Explanation: Use Sequence for large data.
- Code:
- Use case: Large log parsing.
- Why it matters: Lower memory footprint.
69. tailrec factorial¶
- Explanation: Tail recursion optimization.
- Code:
- Use case: Math utilities.
- Why it matters: Avoids stack overflow.
70. Partial function application¶
- Explanation: Pre-bind parameters.
- Code:
- Use case: Preconfiguring mappers.
- Why it matters: Reusable functions.
71. Pipe operator¶
- Explanation: Function composition helper.
- Code:
- Use case: Transform chains in pipelines.
- Why it matters: Readable transformations.
72. Currying¶
- Explanation: Convert binary function to unary chain.
- Code:
- Use case: Reusable predicates.
- Why it matters: Encourages FP patterns.
73. memoize¶
- Explanation: Cache pure function outputs.
- Code:
- Use case: Expensive formatting.
- Why it matters: Performance boost.
74. Either type alias¶
- Explanation: Represent success/failure without exceptions.
- Code:
- Use case: Domain errors.
- Why it matters: Better than throwing.
75. Kotlin contracts for callbacks¶
- Explanation: Non-null guarantees for callbacks.
- Code:
- Use case: Optional listeners.
- Why it matters: Compiler smart casts listener.
76. Inline property accessor¶
- Explanation: Avoids method call overhead.
- Code:
- Use case: Hot getters.
- Why it matters: Micro-optimizations in tight loops.
77. lateinit safety check¶
- Explanation: Verify initialization before use.
- Code:
- Use case: Unit tests checking injection.
- Why it matters: Avoids runtime exceptions.
78. object expression for lightweight singletons¶
- Explanation: Short-lived object instead of class.
- Code:
- Use case: Custom sort.
- Why it matters: No extra class files.
79. useResource¶
- Explanation: Generic closeable handler.
- Code:
- Use case: Cursor usage.
- Why it matters: Prevent leaks.
80. Parcelable via @Parcelize¶
- Explanation: Simplify parcelable models.
- Code:
- Use case: Navigation arguments.
- Why it matters: Removes boilerplate CREATOR code.
81. Result.unwrapOrNull¶
- Explanation: Get value or null.
- Code:
- Use case: Optional pipelines.
- Why it matters: Centralized logging.
82. combineLatest with debounce¶
- Explanation: Debounce combined emissions.
- Code:
- Use case: Form validation on two fields.
- Why it matters: Reduces validator churn.
83. Flow.onStart loading state¶
- Explanation: Emit loading before work.
- Code:
- Use case: Showing progress bar.
- Why it matters: Consistent UX.
84. Flow.onCompletion hide loading¶
- Explanation: Hide spinner when complete.
- Code:
- Use case: UI progress toggles.
- Why it matters: Prevents stuck loading.
85. Lifecycle-aware flow collection¶
- Explanation: Collect flow tied to LifecycleOwner.
- Code:
- Use case: Activities and fragments.
- Why it matters: Auto-cancel on stop.
86. DiffUtil extension¶
- Explanation: Quick DiffUtil callback.
- Code:
- Use case: RecyclerView adapters.
- Why it matters: Less ceremony for stable ids.
87. lazy fast sequence builder¶
- Explanation: Create sequences for streams.
- Code:
- Use case: Demo data generation.
- Why it matters: Infinite lazy data.
88. when expression exhaustive check¶
- Explanation: Enforce exhaustiveness.
- Code:
- Use case: Sealed UI rendering.
- Why it matters: Prevents missing branches.
89. Inline lambda label return¶
- Explanation: Use labels to exit correct scope.
- Code:
- Use case: Early skip in iterations.
- Why it matters: Avoids accidental function return.
90. Sequence windowed¶
- Explanation: Sliding window utility.
- Code:
- Use case: Trend calculation.
- Why it matters: Less manual indexing.
91. chunked processing¶
- Explanation: Process large lists in batches.
- Code:
- Use case: API batch uploads.
- Why it matters: Avoids payload limits.
92. mapNotNullTo¶
- Explanation: Transform and collect non-null.
- Code:
- Use case: Filtering API responses.
- Why it matters: Fewer explicit null checks.
93. flattenMerge flows¶
- Explanation: Merge flow of flows.
- Code:
- Use case: Combine multiple event sources.
- Why it matters: Concurrent emission handling.
94. flatMapLatest search¶
- Explanation: Cancel previous job on new input.
- Code:
- Use case: Search suggestions.
- Why it matters: Avoids outdated results.
95. Channel actor pattern¶
- Explanation: Serialize events through actor.
- Code:
- Use case: MVI reducers.
- Why it matters: Thread-safe reducers without locks.
96. lateinit resettable¶
- Explanation: Clearable lateinit for tests.
- Code:
- Use case: Test hooks.
- Why it matters: Control lifecycle manually.
97. KClass.safeObjectInstance¶
- Explanation: Get object singleton if exists.
- Code:
- Use case: Accessing objects reflectively.
- Why it matters: Avoids reflective creation.
98. property reference reuse¶
- Explanation: Use property refs for keys.
- Code:
- Use case: Bundle keys aligned to properties.
- Why it matters: Prevents typos.
99. Inline expect/actual for multiplatform¶
- Explanation: Platform specific implementations.
- Code:
- Use case: Shared KMP modules.
- Why it matters: Cleaner platform branching.
100. typealias for readability¶
- Explanation: Shorten complex types.
- Code:
- Use case: Adapter callbacks.
- Why it matters: Improves readability of signatures.
🚀 Connect & Support¶
If you found this guide helpful and want to master Android development, Kotlin, and AI integration, let's connect!
- Subscribe for more Dev Content: YouTube @alwayslaxmikant 🔔
- Get real-time updates: X (Twitter) @alwayslaxmikant 🐦
- Follow on Instagram: Instagram @alwayslaxmikant 📸