Kotlin Blogs
Android System Design Interviews
Android System Design is the process of defining the client components, API requirements, and database tables of an app to meet the given requirements.
CoroutineContext in Kotlin
CoroutineContext in Kotlin defines the environment in which a coroutine runs, using elements like Dispatcher, Job, CoroutineName, and CoroutineExceptionHandler.
Parcelable vs Serializable
Parcelable is an Android-specific interface that does not use reflection, so it is faster. Serializable is a Java marker interface that uses reflection and is slower.
String vs StringBuffer vs StringBuilder
String is immutable, StringBuffer is mutable and thread-safe, and StringBuilder is mutable but not thread-safe, which makes it the fastest of the three.
data class in Kotlin
A data class in Kotlin is a class used to hold data. It automatically generates equals(), hashCode(), toString(), copy(), and more for us.
Extension function in Kotlin
An extension function in Kotlin lets us add new functions to existing classes without modifying their source code. We will also learn how it works internally.
remember vs rememberSaveable
In Jetpack Compose, remember keeps the state across recompositions, whereas rememberSaveable also keeps it across configuration changes like screen rotation.
Launch vs Async in Kotlin Coroutines
launch and async both start a coroutine in Kotlin. launch returns a Job with no result, whereas async returns a Deferred that gives us the result.
callbackFlow - Callback to Flow API in Kotlin
callbackFlow converts any Callback to Flow API in Kotlin. We send each value using trySend() and unregister the callback inside the awaitClose block.
Difference between == and === in Kotlin
In Kotlin, == checks structural equality using equals(), whereas === checks referential equality, which means whether both references point to the same object.
StateFlow and SharedFlow
StateFlow and SharedFlow are Hot Flows in Kotlin. StateFlow needs an initial value and keeps only the latest value, whereas SharedFlow can replay many values.
Cold Flow vs Hot Flow
A Cold Flow emits data only when there is a collector and starts fresh for each one. A Hot Flow emits data even without collectors and shares it with all of them.
Unit Testing ViewModel with Kotlin Flow and StateFlow
To unit test a ViewModel with Kotlin Flow and StateFlow, we mock the data layer, use a test dispatcher, and verify the StateFlow values using Turbine.
How does the Kotlin Multiplatform work?
In Kotlin Multiplatform, we write shared code once in Kotlin. It becomes Java bytecode for Android and native code inside a framework for iOS.
Mastering Kotlin Coroutines
Kotlin Coroutines help us run long tasks, like a network call, in the background without blocking the main thread, using simple code that reads from top to bottom.
Callback to Coroutines in Kotlin
We can convert any Callback to Coroutines in Kotlin by wrapping it inside suspendCoroutine or suspendCancellableCoroutine, and resuming with the result.
Retry Operator in Kotlin Flow
The Retry Operator in Kotlin Flow (retry and retryWhen) retries a failed flow based on a condition. We can also use it with exponential backoff delay.
Long-running tasks in parallel with Kotlin Flow
We can run long-running tasks in parallel with Kotlin Flow using the zip operator, which runs both tasks together and combines their results.
Retrofit with Kotlin Coroutines
To use Retrofit with Kotlin Coroutines, we mark the API functions with suspend and call them from a coroutine inside the ViewModel. We will build it with MVVM.
coroutineScope vs supervisorScope
A coroutineScope cancels all its children when any one child fails, whereas a supervisorScope does not cancel the other children when one of them fails.
Retrofit with Kotlin Flow
To use Retrofit with Kotlin Flow, we wrap the suspend API call inside a flow builder and collect the result inside the ViewModel. We will build it with MVVM.
Room Database with Kotlin Flow
To use Room Database with Kotlin Flow, we return a Flow from the database layer, emit the data from Room, and collect it inside the ViewModel.
crossinline in Kotlin
crossinline in Kotlin is used to avoid non-local returns from a lambda that is passed to an inline function. We will learn it with a simple example.
inline function in Kotlin
An inline function in Kotlin tells the compiler to insert the complete body of the function wherever that function is called, which avoids the call overhead.
noinline in Kotlin
noinline in Kotlin is used when we do not want all the lambdas passed to an inline function to be inlined. We mark those lambda parameters as noinline.
init block in Kotlin
The init block in Kotlin runs when an object is created, right after the primary constructor, and lets us write the initialization code that it cannot hold.
Companion object in Kotlin
A companion object in Kotlin lets us call a function or access a property using the class name, without creating an object, like static in Java.
lateinit vs lazy in Kotlin
In Kotlin, lateinit is used with var when we will initialize the variable later, whereas lazy is used with val to create the object only on its first access.
Infix notation in Kotlin
Infix notation in Kotlin lets us call a function without the dot and parentheses, so that the code looks much more like a natural language.
Open keyword in Kotlin
In Kotlin, classes, functions, and variables are final by default. We mark them with the open keyword to allow them to be inherited or overridden.
Dispatchers in Kotlin Coroutines
Dispatchers help Kotlin Coroutines decide the thread on which a task runs. The types are Dispatchers.Default, Dispatchers.IO, Dispatchers.Main, and Unconfined.
Mastering Flow API in Kotlin
Flow API in Kotlin is an asynchronous data stream that emits values to a collector and completes with or without an exception. Let's master it step by step.
JvmField Annotation in Kotlin
The JvmField annotation in Kotlin tells the compiler not to generate getters and setters, so that Java code can access the property directly as a field.
JvmOverloads Annotation in Kotlin
The JvmOverloads annotation tells the Kotlin compiler to generate overloads for a function or constructor with default parameters, so that Java can call it.
Avoid nesting by handling errors first
Avoid nesting by handling the errors first and returning early. This keeps the main logic at the top level of the function and makes the code easy to read.
JvmStatic Annotation in Kotlin
The JvmStatic annotation in Kotlin lets Java code call a function of a named object or companion object directly, without using INSTANCE or Companion.
Advantage of using const in Kotlin
The advantage of using const in Kotlin is that the value gets inlined at compile time, so there is no overhead to access that variable at runtime.
partition - filtering function in Kotlin
partition is a Kotlin filtering function that splits a collection into two lists, one with the elements that match the predicate and one with those that do not.
AssociateBy - List to Map in Kotlin
associateBy is a Kotlin collection function that converts a list into a map, where we decide the key for each item. We will learn it with an example.
Remove duplicates from an array in Kotlin
We can remove duplicates from an array in Kotlin using distinct(), toSet(), toMutableSet(), or toHashSet(). We choose one based on our use case.
Jetpack DataStore Preferences
Jetpack DataStore is the new data storage solution that replaces SharedPreferences. It is built on Kotlin Coroutines and Flow and stores data asynchronously.
Kotlin Flow Zip Operator for Parallel Multiple Network Calls
The Kotlin Flow zip operator combines the emissions of two flows into one. We can use it to make multiple network calls in parallel and get both results together.
Instant Search Using Kotlin Flow Operators
We can build instant search in Android using Kotlin Flow operators like debounce, filter, distinctUntilChanged, and flatMapLatest, to avoid extra network calls.
Creating Flow Using Flow Builder in Kotlin
In Kotlin, we can create a Flow using four flow builders, which are flowOf(), asFlow(), flow{}, and channelFlow{}. We will learn each one with examples.
Exception Handling in Kotlin Flow
In Kotlin Flow, we handle exceptions using the catch operator. The flow can complete with or without an exception, and catch lets us handle it gracefully.
Terminal Operators in Kotlin Flow
Terminal operators in Kotlin Flow, like collect, are the operators that actually start the flow by connecting the flow builder and operators with the collector.
suspend function in Kotlin Coroutines
A suspend function in Kotlin Coroutines is a function that can be started, paused, and resumed, without blocking the thread. Let's see how it works.
Kotlin withContext vs Async-await
withContext does not create a new coroutine. It only shifts the context of the current one, whereas async creates a new coroutine and we use await() for the result.
Room Database with Kotlin Coroutines
To use Room Database with Kotlin Coroutines, we mark the DAO functions with suspend and call them from a coroutine. We will build it with MVVM.
Parallel Multiple Network Calls Using Kotlin Coroutines
We can make multiple network calls in parallel using Kotlin Coroutines by starting each call with async and then calling await() on each to get the results.
Unit Testing ViewModel with Kotlin Coroutines and LiveData
To unit test a ViewModel with Kotlin Coroutines and LiveData, we mock the data layer with Mockito, use a TestCoroutineRule, and check the LiveData values.
MVVM Architecture - Android Tutorial
MVVM (Model-View-ViewModel) is an Android architecture that removes tight coupling between components. We will learn it and build a project with it.
Higher-Order Functions and Lambdas in Kotlin
A lambda in Kotlin is an anonymous function that we can treat as a value. A higher-order function is a function that takes a function as a parameter or returns one.