1. What is "hot flow" and "cold flow" in Kotlin.
Hot flow: Is type of flow that produces values regardless of whether there are active collectors.
While “cold flows,” which only emit values when there is an active collector.
1. What is diff between launch and async
in Kotlin coroutine.
Launch: Launch can be used at places where
users do not want to use the returned result.
Async: It is also used to start the coroutines, but it
blocks the main thread at the entry point of the await() function in
the program
Launch
|
async
|
1.
launch is
basically fire and forget.
|
Async is basically
performing a task and return a result.
|
2.
launch{} does
not return anything
|
async{ }, which has an
await() function returns the result of the coroutine.
|
3.
launch{} cannot
be used when you need the parallel execution of network calls.
|
Use async only when you
need the parallel execution network calls.
|
4.
launch{} will
not block your main thread.
|
Async will block the main
thread at the entry point of the await() function.
|
5.
It is not
possible for the launch to work like async in any case or condition.
|
If you use async and do
not wait for the result, it will work exactly the same as launch.
|
6.
Example: It can
be used at places involving tasks like update or changing color like fetch
User And Save In Database.
|
Example: Imagine the
condition, when we have to fetch two users’ data from the database by using
two parallel network calls and then use them for computing some results based
on their data.
|
|
|
2. what is coroutines scope in kotlin.
There are basically 3
scopes in Kotlin coroutines:
A.
Global Scope:-
GlobalScope is a top level CoroutineScope that is operating as long as the
application is alive. The task will remains alive until the app killed. Since
it’s alive along with application lifetime, GlobalScope is a
singleton object.
Ex:-
GlobalScope.launch(Dispatchers.Main) {
println("loading..")
delay(3000)
println("job is done")
}
B.
RunBlocking:- RunBlocking is
a scope builder that will give us CoroutineScope but with blocking.
So if we use RunBlocking instead of regular CoroutineScope then
it will block current thread and wait until code inside runBlocking executed.
C.
LifeCycle Scope:-
When we’re using CoroutineScope in Activity/Fragment we have to make
sure the running coroutine stop when we destroy the Activity/Fragment to avoid
memory leak and resource waste. Therefore we should check and cancel CoroutineScope when
the lifecycle owner is about to be destroyed. In this case by using LifecycleScope we
don’t have to manually check and cancel the running coroutine before lifecycle
owner is destroyed. LifecycleScope tied to the lifecycle so the
coroutine lifetime will follow the lifecycle owner lifetime.
D.
ViewModel Scope:-
ViewModelScope is similar to LifecycleScope except it happens on
ViewModel. Without ViewModelScope usually we want to cancel the
coroutine on clear state. But using this ViewModelScope we don’t need
to cancel coroutine manually, we can rely onViewModelScope to cancel
automatically if the ViewModel is about to be cleared.
1. Use ViewModelScope if
you want to run coroutine in ViewModel.
2. Use LifecycleScope if you want to run coroutine in
lifecycle owner (Activity/Fragment)
3. Use CoroutineScope if you want to run coroutine for places
other than ViewModel and lifecycle owner.
4. Use GlobalScope if you want to run coroutine with
application scope running task.
5. Use RunBlocking if you want to run suspend function or
library on regular blocking code.
Using LifecycleScope we can also use special launch condition:
1. launchWhenCreated .
2. launchWhenStarted.
3. launchWhenResumed.
3. Can we call any API in MAIN thread .
No It will give NetworkOnMainThreadException
4. What is SOLID Principal in
programming.
A. Single Responsibility Principle (SRP):-
Every class should have a single responsibility or single job or single purpose.
B. Open/Closed Principle: - “Software
entities (classes, modules, functions, etc.) should be open for extension, but
closed for modification” which means you should be able to extend a class
behavior, without modifying it.
C. Liskov’s Substitution Principle (LSP):-
This principle ensures that any class that is the child of a parent class
should be usable in place of its parent without any unexpected behavior.
Ex: One of the classic
examples of this principle is a rectangle having four sides. A rectangle’s
height can be any value and width can be any value. A square is a rectangle
with equal width and height. So we can say that we can extend the properties of
the rectangle class into square class.
D. Interface Segregation Principle (ISP):-
“do not force any client to implement an interface which is irrelevant
to them“.
Ex: Suppose if you
enter a restaurant and you are pure vegetarian. The waiter in that restaurant
gave you the menu card which includes vegetarian items, non-vegetarian items,
drinks, and sweets.
E. Dependency Inversion Principle (DIP):-
High-level modules should not depend on low-level modules. Both should
depend on abstractions“.
Ex:- In a software
development team, developers depend on an abstract version control system
(e.g., Git) to manage and track changes to the codebase. They don’t depend on
specific details of how Git works internally.
5. Explain the concept of side effects
in Jetpack Compose.
Side effects in Jetpack Compose refer to operations that have additional
effects beyond modifying the UI state. Examples include making network
requests, accessing databases, or updating shared preferences. Side effects are
handled using functions like LaunchedEffect or DisposableEffect,
which allow you to perform these operations while ensuring proper lifecycle
management.
6. How can you handle asynchronous
operations in Jetpack Compose?
Asynchronous operations in Jetpack Compose can be handled using Kotlin
coroutines and the suspend function modifier. You can launch coroutines within
Composable functions using LaunchedEffect or other coroutine builders.
This allows you to perform asynchronous operations in background and update the UI when the operation completes.
7. Difference between stateflow and
sharedflow.
StateFlow is used to represent and observe state changes, while SharedFlow
is used to share data among multiple parts of an application.
8. What are Compose key events, and how
are they used?
Compose key events allow you to handle keyboard events, such as key
presses, in Jetpack Compose. You can use the onKeyEvent modifier to
listen to key events and define the corresponding actions within Composable
functions.
9. What is the purpose of remember in
Jetpack Compose, and how is it used?
The remember function in Jetpack Compose is used to create and
store a value that survives recomposition. It allows you to preserve and reuse
expensive computations or expensive objects, optimizing performance by avoiding
unnecessary recomputations.
10.What is the role of StateFlow and
SharedFlow in Jetpack Compose?
StateFlow and SharedFlow are part of the Kotlin coroutines library and
can be used in Jetpack Compose for managing state and asynchronous data
streams. StateFlow represents a state value that can be observed for changes,
while SharedFlow represents a hot data stream that can be collected by multiple
collectors.
11.Explain the concept of lazy
composition in Jetpack Compose.
Lazy composition in Jetpack Compose allows you to defer the execution of
expensive Composable functions until they are actually needed. It helps
optimize performance by only recomposing and rendering UI components when they
become visible or relevant to the current state.
12.How to secure android app while
developing?
1.
Data Encryption
2.
Regular security Update
3.
Secure Authentication.
4.
Use trusted SDK and Library.
5.
Use https connection for api.
6.
Avoid saving security inputs to app constant.
13.How to do memory management in Kotlin
android?
a. Enable garbage collection manually.
To force-start the
garbage collector, call kotlin.native.internal.GC.collect(). This method
triggers a new collection and waits for its completion.
b. enable the feature, set the following
compiler option in your gradle.properties file:
kotlin.native.binary.enableSafepointSignposts=true.
c. Avoid using “enum”. Enum will double
memory allocation than ordinary static constant, so do not use it.
d. Avoid creating unnecessary objects.
Do not allocate memory especially for short-term temporary objects
e. Avoid keeping running background service
or task unless it’s actively performing a task.
14.What
is job and supervisor job in Kotlin.
Use a Job when you want to
create a hierarchy of coroutines where the failure of one child cancels the
entire hierarchy. Use SupervisorJob when you want to create a hierarchy
where child coroutines can fail independently without affecting their siblings.
1. what is observable fields and live
data
LiveData is
an observable data holder class which just observes the changes in the View
layer and updates the view.
But, before this there is a ObservableField on similar
grounds like Livedata and it was also a type of Data holder which can be
observed to the get the data.
ObservableField <T> is not Lifecycle aware but
LiveData is. That means LiveData will only update app component observers that
are in an active lifecycle state and not which are inactive. We have to do
manual handling of Lifecycle awareness in ObservableField
2. what is difference between flow and
live data.
a. Flow and LiveData are both are components
of the Android Architecture Components that help manage and communicate data
between different parts of an Android application, such as UI components and
data sources. They serve similar purposes, but they have some differences in
terms of usage and functionality.
b. LiveData: LiveData is an observable
data holder class which just observes the changes in the View layer and updates
the view. It’s lifecycle-aware, which means it automatically manages the
observer’s lifecycle and only updates when the observer is in an active
state (e.g., the UI is visible).
Difference between
flow and Livedata are:-
Lifecycle-aware: LiveData is lifecycle-aware, which means it automatically
manages the lifecycle of the observers, ensuring that updates are only
delivered when the observer is in an active state.
Flow, on the other hand, is not
lifecycle-aware by default.
Flexibility: Flow
provides more flexibility and is not limited to Android. It can be used in
non-Android Kotlin applications as well. Flow is suitable for more complex asynchronous
data operations, while LiveData is typically used for simpler UI updates.
Error Handling: Flow has
better support for handling errors and exceptions compared to LiveData.
By default
LiveData is lifecycle aware but flow is not, to make flow as lifecycle aware we
have to use collectAsStateWithLifecycle . Ex: - write
like below
@Composable
fun MyScreen()
{
val state by
viewModel.state.collectAsStateWithLifecycle()
}
3. What is EarlyEntryPoint and
AndroidEntryPoint in hilt.
Entry points are important because they define that which
activity or fragment is the entry point to hilt control flow.
EarlyEntryPoint is used to create a Hilt entry point before the singleton
component is available in a Hilt test, It mainly used in hilt test.
AndroidEntryPoint
is a specialized tool for defining and accessing entry points for Android
classes.
4.
How to stop recompositing in Kotlin.
Key Tips to
Avoid Unnecessary Recomposition:-
a.
Wrap Callbacks with remember: Prevent
unnecessary recompositions by ensuring your callback functions don't change on
every recomposition.
var text by
remember { mutableStateOf("") }
val onTextChanged = remember { {
newText: String -> text = newText } }
b.
Use Stable Data Types: Ensure the data types used in your state are stable. This means
they should not change their identity (reference) if their content remains the
same. Stable data types help prevent unnecessary recompositions.
c.
Use LazyColumn with Stable Keys: Provide
stable keys for each item in lazy layouts to help Compose identify which items
have changed and avoid unnecessary recompositions.
@Composable
fun MyLazyColumn(items: List<String>) {
LazyColumn {
items(items, key = { it }) { item
->
Text(item)}}}
D. Use LaunchedEffect : run suspend functions in the scope of
a composable.
To perform work over
the life of a composable and have the ability to call suspend functions, use
the LaunchedEffect composable.
When LaunchedEffect enters the Composition, it launches a coroutine
with the block of code passed as a parameter. The coroutine will be cancelled
if LaunchedEffect leaves the composition
Stable Data Types:
·
Primitive Types: Int, Float, Boolean, etc., are
stable and do not cause unnecessary recompositions.
·
Immutable
Collections: Use ImmutableList and PersistentList from
kotlinx for handling dynamic data without triggering unnecessary UI updates.
Unstable Data Types:
·
Lists: Creating a new list instance each time can
cause recompositions.
·
MutableList: Similar to Lists, but with additional
mutability, which can lead to identity changes.
·
MutableSet: Changes to the set’s content or its identity
can cause recompositions.
·
MutableMap: Any changes in the map or creating new
instances can lead to recompositions.
5.
what is work manager in Kotlin.
It is a
library in android jectpack . we use work manager to do task in background.It
will perform the task even if user move to other screen or app or user close
the app.
WorkManager
can run task(s) in background for one time or many time or Periodically.
class WorkerClass(appContext:
Context, workerParams: WorkerParameters): Worker(appContext, workerParams) {
override fun
doWork(): Result {
// Enter work
details to perform on background
Log.d("WorkerClass","It's
Working")
// Task result
return
Result.success() } }
The Result returned from doWork() informs the
WorkManager whether the work succeeded and, in the case of failure, whether or
not the work should be retried. These are Result.success(),
Result.failure(), Result.retry().
The WorkManager
is an API which can schedule your future asynchronous tasks and can run
them in the background. The tasks assigned to the WorkManager are executed even
if the user is outside the app or app is closed. what is viewModel
6.
What is
ViewModel in android or Kotlin.
ViewModel is a
class that is responsible for preparing and managing the data for an Activity
or a Fragment .
ViewModel will not be
destroyed if its owner is destroyed for a configuration change (e.g. rotation).
The new instance of the owner will just re-connect to the existing ViewModel.
The purpose of the
ViewModel is to acquire and keep the information that is necessary for an
Activity or a Fragment. The Activity or the Fragment should be able to observe
changes in the ViewModel. ViewModels usually expose this information via LiveData
or Android Data Binding.
ViewModel's only
responsibility is to manage the data for the UI. It should never access
your view hierarchy or hold a reference back to the Activity or the Fragment.
7.
How to
make horizontal and vertical scroll in jetpack compose.
val
scrollStateHorizontal = rememberScrollState()
val
scrollStateVertical = rememberScrollState()
Column(
Modifier
.verticalScroll(scrollStateVertical)
)
{
HorizontalPager(/*...*/)
OtherScrollableContent(/*...*/)
}
8.
How to pass a view model to another fragment.
Each ViewModel
is (shold be) bound to a single LifeCycleOwner, which refers to Fragment or
Activity. In other words, Each ViewModel is bound to a single Fragment or
Activity.
For sharing
(ViewModel's) data between Fragments, use SharedViewModel pattern, the
idea is, this ViewModel will be bound to the outer (parent) Activity, and for
each its child Fragment you can get this ViewModel instance by using:
private val
model: SharedViewModel by activityViewModels()
9.
Can we extend Data class in Kotlin.
No, in Kotlin,
data classes cannot be directly extended or subclassed.
10. what is
coroutines?
Kotlin
coroutines are a concurrency design pattern that helps simplify
asynchronous code and manage long-running tasks in Android apps. They are
lightweight threads that can be used to write simplified code that keeps an app
responsive.
11. Life cycle of coroutines in Kotlin.
We are managing lifecycle of coroutine by LifeCycle Scope.
The lifecycle scope is the same as the global scope, but the only
difference is that when we use the lifecycle scope, all the coroutines
launched within the activity also dies when the activity dies.
12. how to handle exception in
coroutine .
a. using try catch
b. using CoroutinExceptionHandler
What are
the benefits of Using LiveData?
- No memory Leaks : As the observers are bound to
the lifecycle of the app, when not required the it is destroyed
- No Crashes due to Stopped
Activity : As
the Activity is not in use, so is the LiveData. So the data streaming
stops which stops the crashes in the back stack.
- Configuration Changes : It handles the latest data when
view is recreated due to screen rotation.
1. What
are the key features of Kotlin?
- Null safety, eliminating the danger of null
references from code, which are a common source of bugs in Java
- Interoperability with Java, enabling developers to use
existing Java libraries and frameworks
- Conciseness, which helps reduce boilerplate
code and make the codebase more concise and readable
- Type inference, meaning that Kotlin can infer
types of variables and return types of functions
- Extension functions, enabling developers to add new
functionalities to existing classes without modifying source code
Other
features we might mention :-coroutines, smart casts, functional programming
support, data classes, and Kotlin’s rich standard library.
2. How
does Kotlin handle null safety?
Kotlin
handles null safety by differentiating nullable and non-nullable types.
Variables can't hold null values unless explicitly declared nullable with?
- The safe call operator ? :- prevents null pointer
exceptions
- The Elvis operator ?: :- When working with nullable types, you can check
for null and provide an alternative value.
val b: String? = null
val l: Int = if (b != null) b.length else 0
println(l)
====removed with elvis operate====
Val l:Int=b?.length?:0
The non-null assertion operator ! ! :- The not-null assertion
operator !! converts any value to a non-nullable type. Ex:-
// Assigns a nullable string to a variable
val b: String? = "Kotlin"
// Treats b as non-null and accesses its length
val l = b!!.length
println(l)
// 6
3. What
is type inference in Kotlin?
In Kotlin,
type inference is the ability of the compiler to automatically determine the
type of a variable, function parameter, or return type without explicit type
annotations.
4.
Explain the use of the when expression in Kotlin.
In
Kotlin, when replaces the switch operator of
other languages like Java. A certain block of code needs to be executed when
some condition is fulfilled. when can be used as a statement with
or without else branch.
fun main
(args : Array<String>) {
print("Enter
the name of heavenly body: ")
var
name= readLine()!!.toString()
when(name)
{
"Sun"
-> print("Sun is a Star")
"Moon"
-> print("Moon is a Satellite")
"Earth"
-> print("Earth is a planet")
else
-> print("I don't know anything about it")
}
}
It’s concise
and readable, handling many cases without needing
multiple if-else statements.
5. How do
you handle exceptions in Kotlin?
Top
developers will know that to handle exceptions, they need to use try, catch,
and finally blocks, similarly to Java:
- Try blocks serve to enclose
code that might throw an exception
- Catch blocks handle
exceptions
- Finally blocks cleans up
code that runs regardless of an exception
6. What
is the purpose of the sealed class in Kotlin?
In Kotlin, a
sealed class is a special kind of abstract class that limits which classes
can inherit from it. Sealed classes are useful when there are a limited
number of possible types for an object, or when you want to ensure code safety
and eliminate runtime errors.
7. How
does Kotlin support object-oriented programming?
Kotlin
supports object-oriented programming with classes, objects, inheritance, and
interfaces. The language also supports abstract classes and methods, providing
a way to define templates for other classes to extend.
8.
Explain the use of data classes in Kotlin.
Top
applicants will know that data classes hold data and automatically provide
standard functionality like equals(), hashCode(), toString(),
and copy().
To declare a
data class, a developer needs to use the data keyword. These classes
make it easier to create and manage objects that primarily store values,
reducing boilerplate code and ensuring consistency in common operations.
9. What
are the differences between a class and an object in Kotlin?
Expect
candidates to explain that:
- A class is a blueprint for
creating objects, defining properties and methods that the objects will
have
- An object is an instance of a class
Kotlin also
has a special type of object called a singleton, created using the object keyword.
This singleton object is a class with only one instance, used for creating
singletons without needing a class.
10. How
do you implement inheritance?
For this, we
have to use the open keyword
to make a class inheritable and then, use the : symbol to extend the base
class.
The derived
class can override properties and methods of the base class using
the override keyword. This enables coders to create a class hierarchy
where subclasses inherit and potentially modify behavior from their parent
classes.
11. What
is a companion object?
In Kotlin, a
companion object is a singleton object that is associated with a class. It's a
way to group static-like functionality with a class, similar to static methods
and fields in Java. However, unlike Java, companion objects are instances of a
class, so they can implement interfaces, have their own state, and can be
passed around like any other object.
Here are
some key features of companion objects:
1. Singleton:
A companion object is a singleton, meaning only one instance exists per class.
2.
Associated with a class: A companion object is associated with a specific
class and has access to its private members.
3. Can
implement interfaces: A companion object can implement interfaces, which
allows for more flexibility and polymorphism.
4. Can
have state: Unlike Java's static methods and fields, companion objects can
have their own state.
5. Can be
passed around: Companion objects can be passed as arguments to functions or
returned from functions.
To declare a
companion object in Kotlin, you use the companion keyword inside a class:
class
MyClass {
companion object {
// companion object members go here
}
}
You can then
access the companion object's members using the class name:
MyClass.companionObjectMember()
12. How
does Kotlin support functional programming?
Top Kotlin
features that support functional programming include:
- Higher-order functions
- Lambda expressions
- Immutability
In Kotlin,
developers can pass functions as parameters, return them, or assign them to
variables. Additionally, Kotlin’s standard library includes functions
like map, filter, and reduce for processing collections in
a functional style.
Extension
functions and immutable data structures further enhance Kotlin’s functional
programming capabilities, allowing for concise and expressive code.
13. What
are higher-order functions?
Higher-order
functions (HOFs) in Kotlin are functions that take other functions as arguments
or return functions as output. This allows for more flexibility, abstraction,
and reuse of code. Here are some key aspects of HOFs in Kotlin:
Functions
as arguments:
- You can
pass a function as an argument to another function.
- The passed
function is called a "callback" or "lambda".
Example:
fun
executeCallback(callback: () -> Unit) {
callback()
}executeCallback
{ println("Hello, HOF!") }
Functions
as return types:
- A function
can return another function.
- The
returned function is called a "closure".
Example:
fun createAdder(x:
Int): (Int) -> Int {
return { y -> x + y }
}
val addFive
= createAdder(5)
println(addFive(10))
// prints 15
Lambda
expressions:
- A concise
way to represent small, single-method functions.
- Can be
used as arguments or return types.
Example:
val sum = {
x: Int, y: Int -> x + y }
println(sum(2,
3)) // prints 5
Function
types:
- Kotlin has
a built-in syntax for representing function types.
- (Int)
-> Unit represents a function that takes an Int and returns Unit (no return
value).
Example:
val
callback: (Int) -> Unit = { x -> println(x) }
Benefits
of HOFs:
- Code reuse
and abstraction
- More
expressive and flexible code
- Enables
functional programming techniques
Common
use cases for HOFs in Kotlin include:
- Callbacks
and event handlers
- Data
processing and transformation
- Functional
programming techniques like map, filter, and reduce
- Creating
DSLs (Domain-Specific Languages)
14. What
are lambda expressions in Kotlin? How are they used?
In Kotlin,
lambda expressions are a concise way to represent small, single-method
functions. They are anonymous functions that can be defined inline, making your
code more expressive and concise. Here's a breakdown:
Syntax:
- {
parameters -> body }
- Parameters
are separated by commas, and the body is an expression or a block of code.
Example:
- { x:
Int, y: Int -> x + y } (adds two integers)
- {
println("Hello, Lambda!") } (prints a message)
Key
features:
- Anonymous:
No need to declare a named function.
- Single-method:
Can only contain a single expression or statement.
- Concise:
Shorter than declaring a separate named function.
- Can be
used as arguments, return types, or assigned to variables.
Use
cases:
- Event
handlers (e.g., button clicks)
- Data
processing and transformation (e.g., mapping, filtering)
- Functional
programming techniques (e.g., reduce, fold)
- Creating
small, one-time-use functions
Benefits:
- Reduces
boilerplate code
- Improves
code readability
- Enables
functional programming techniques
Common
lambda types:
- (Int)
-> Unit (takes an Int, returns no value)
- (String)
-> Boolean (takes a String, returns a Boolean)
- (Int, Int)
-> Int (takes two Ints, returns an Int)
Type
inference:
- Kotlin can
often infer the lambda's parameter types and return type, making the code even
more concise.
Example:
val sum =
{ x: Int, y: Int -> x + y }
// or, using
type inference
val sum =
{ x, y -> x + y }
15. How
do you create and use inline functions?
Inline
functions in Kotlin are functions marked with the inline keyword,
which tells the compiler to insert the function's body directly into the places
where it's called. This reduces the overhead of function calls, especially for
small, frequently-used functions.
Expert
candidates will know that inline functions are particularly useful with
higher-order functions to avoid creating additional objects for lambda
expressions, improving performance.
16. How
do you work with Kotlin's delegation pattern?
In Kotlin,
the delegation pattern is a design pattern that allows an object to forward
method calls to another object, known as the delegate. This enables:
1. Code
reuse: Avoid duplicating code by delegating to an existing class.
2. Flexibility:
Change the delegate at runtime, allowing for more dynamic behavior.
3. Decoupling:
Separate the dependent components, making the code more modular.
There are
two types of delegation in Kotlin:
1. Interface
delegation: Implement an interface by delegating to another object that
implements the same interface.
Example:
interface
Printable {
fun print()
}
class
RealPrinter : Printable {
override fun print() {
println("Printing...")
}
}
class
DelegatePrinter(private val printer: Printable) : Printable by printer
fun
main() {
val realPrinter = RealPrinter()
val delegatePrinter =
DelegatePrinter(realPrinter)
delegatePrinter.print() // Output:
Printing...
}
1. Class
delegation: Delegate to a class, which can be useful for wrapping or
extending existing classes.
Example:
class
BaseClass {
fun foo() {
println("Foo from BaseClass")
}
}
class
DerivedClass(private val base: BaseClass) : BaseClass() by base
fun
main() {
val base = BaseClass()
val derived = DerivedClass(base)
derived.foo() // Output: Foo from BaseClass
}
In both
cases, the by keyword is used to specify the delegate.
Benefits
of the delegation pattern in Kotlin:
- Reduces
code duplication
- Increases
flexibility and modularity
- Simplifies
code maintenance and extension
Common
use cases:
- Wrapper
classes
- Adapters
17. Can
you give me examples of use cases for type aliases?
In Kotlin,
type aliases allow you to assign a new name to an existing type, making your
code more readable and concise. You can create an alias for:
1. built-in
types: Rename primitive types, like Int or String.
2. Complex
types: Simplify nested or generic types, like Map<String,
List<Int>>.
3. Custom
classes: Create shorter names for your own classes or interfaces.
Benefits:
- Improves
code readability
- Reduces
verbosity
- Enhances
maintainability
Use cases:
- Simplify
complex generic types
- Create
domain-specific language (DSL)
- Shorten
long class names
- Improve
code consistency
Notes:
- Type
aliases do not create new types, but rather new names for existing types.
- Aliases
can be used anywhere the original type can be used.
- You can
use type aliases in type parameters, function parameters, and return types.
18. How
do you handle multi-threading?
Kotlin
addresses multi-threading primarily through coroutines, which are lightweight,
non-blocking threads. Coroutines simplify asynchronous programming by enabling
developers to write code sequentially while handling concurrency.
19. What
is Kotlin's approach to asynchronous programming?
Use this
question to follow up on the previous one.
For
asynchronous programming, Kotlin uses coroutines, which enable software
engineers to:
- Write code sequentially, making it easier to read and
maintain, while still performing tasks concurrently
- Launch background tasks without blocking
the main thread,
ensuring smooth and responsive applications
Additionally,
they can use functions like launch to start a new coroutine
and async to perform tasks that return results.
20. What
are some common issues you might face when using Kotlin with Java?
Some of the
commonly occurring problems when using Kotlin with Java include:
- Differences in nullability
handling, as Kotlin distinguishes nullable and non-nullable types while
Java does not
- Kotlin’s extension functions and
properties, which might not be directly accessible from Java
- Differences in method signatures
due to Kotlin’s default parameter values, which can lead to
interoperability issues
21. How
do you use Java's SAM interfaces in Kotlin?
Kotlin
simplifies the use of Java's SAM (Single Abstract Method)
interfaces by allowing lambda expressions to be used wherever a SAM interface
is expected.
Instead of
creating an anonymous class, developers can pass a lambda directly. For
example, if they have a Java interface with a single method, they can implement
it in Kotlin like this: button.setOnClickListener { view -> /* handle
click */ }.
In Kotlin, a
Single Abstract Method (SAM) is an interface with only one
abstract method. SAM interfaces are used to create functional interfaces, which
can be implemented using lambda expressions.
Characteristics:
1. Interface
with single abstract method
2. No state,
only behavior
3. Can be
implemented using lambda expressions
22. How
do you configure Kotlin compiler options?
Developers
can configure Kotlin compiler options in the build.gradle file if they're using
Gradle. For this, they need to use the kotlinOptions block to set options
like jvmTarget, freeCompilerArgs, and languageVersion. For
example:
compileKotlin
{
kotlinOptions
{
jvmTarget =
"1.8"
freeCompilerArgs
= ["-Xjsr305=strict"]
}
}
This enables
them to customize the Kotlin compiler behavior according to the project's
needs.
24. Explain
the use of Kotlin in Android development.
Expect
candidates to explain that Kotlin is widely used in Android development due to
its concise syntax, null safety, and interoperability with Java. Google
officially supports Kotlin for Android development, making it a preferred
language for new Android projects.
Kotlin’s
features, such as extension functions and coroutines, simplify common tasks
like view binding and asynchronous programming. Plus, Android Studio provides
robust support for Kotlin, including tools for converting Java code to Kotlin.
25. How
do you use Kotlin's collection APIs?
Kotlin's
collection APIs provide functions for manipulating collections like lists,
sets, and maps. Coders can create collections using functions like listOf,
setOf, and mapOf.
Additionally,
Kotlin offers functional methods such as map, filter, reduce,
and fold to perform operations on collections. This makes collection
operations expressive and easy to understand.
Extra 40
Kotlin interview questions you can ask applicants
1.
How
does Kotlin ensure interoperability with Java?
2.
How do you define and use interfaces in Kotlin?
Keyword interface is used to define interfaces in Kotlin.
3.
What
are primary and secondary constructors in Kotlin?
A constructor is a special member function that is
invoked when an object of the class is created primarily to initialize
variables or properties. A class needs to have a constructor and if we do not
declare a constructor, then the compiler generates a default constructor
Primary Constructor:-
The primary constructor is initialized in the class header,
and goes after the class name, using the constructor keyword
Secondary Constructor: -
Kotlin may have one or more secondary constructors. Secondary
constructors allow initialization of variables and allow to provide some logic
to the class as well. They are prefixed with the constructor keyword.A
Kotlin class may have one or more than one secondary constructors.
4.
Explain the concept of extension functions.
Extension functions, enabling developers to add new functionalities to existing
classes without modifying source code
5.
How do you override methods in Kotlin?
Using override keyword
6.
What’s
the difference between abstract and open keywords?
Abstract keyword used to create abstract class and
Open
keyword use to make any class inheritable.
7.
Collection in Kotlin.
In Kotlin, collections are used to store and manipulate
groups of objects or data. There are several types of collections available in
Kotlin.
Types of Collections
In Kotlin collections are categorized into two forms.
a)
Immutable Collection
b)
Mutable Collection
1. Immutable Collection
It supports only read-only functionalities and can not be
modified its elements. Immutable Collections and their corresponding methods
are:
- List – listOf() and
listOf<T>() :- Ordered collections of elements that allow
duplicates.
- Set – setOf() :- Unordered
collections of unique elements.
- Map – mapOf() :- Collections
of key-value pairs, where each key is unique.
List – It is an ordered collection in which we can access elements or items by
using index – integer numbers that define a position for each element. Elements
can be repeated in a list any number of times. We can not perform add or remove
operations in the immutable list.
// An example for immutable list
fun
main(args: Array<String>) {
val
immutableList =
listOf("Mahipal","Nikhil","Rahul")
// gives compile
time error
//
immutableList.add = "Praveen"
for(item in
immutableList){
println(item)
}
}
Set –
It is a collection of unordered elements also it does not support duplicate
elements. It is a collection of unique elements. Generally, the order of set
elements does not have a significant effect. We can not perform add or remove
operations because it is an immutable Set.
NOTE: we can add any string and integer value to list and set if we don’t
specify the type:
Val itemset=setoff(1,2,”raja”)
Val item=setoff<String>(1,4,”raja”)//it will give error as set is
define as string type so it will not contain integer value. Same for list also.
fun
main(args: Array<String>) {
// initialize
with duplicate values
// but output
with no repetition
var
immutableSet = setOf(6,9,9,0,0,"Mahipal","Nikhil")
// gives compile
time error
//
immutableSet.add(7)
for(item in
immutableSet){
println(item)
}
Map –
Map keys are unique and hold only one value for each key, it is a set of
key-value pairs. Each key maps to exactly one value. The values can be
duplicates but keys should be unique. Maps are used to store logical
connections between two objects, for example, a student ID and their name. As
it is immutable its size is fixed and its methods support read-only
access.
// An example for immutable map
fun main(args : Array<String>) {
var
immutableMap = mapOf(9 to "Mahipal",8 to "Nikhil",7 to
"Rahul")
// gives compile
time error
//
immutableMap.put(9,"Praveen")
for(key in
immutableMap.keys){
println(immutableMap[key])
}
}
2. Mutable Collection
It supports both read and write functionalities. Mutable
collections and their corresponding methods are:
- List –
mutableListOf(),arrayListOf() and ArrayList
- Set – mutableSetOf(),
hashSetOf()
- Map – mutableMapOf(),
hashMapOf() and HashMap
List – Since mutable list supports read and write operation, declared
elements in the list can either be removed or added.
var
mutableList =
mutableListOf("Mahipal","Nikhil","Rahul")
// we can modify
the element
mutableList[0] =
"Praveen"
// add one more
element in the list
mutableList.add("Abhi")
for(item in
mutableList){
println(item)
}
Set –
The mutable Set supports both read and write functionality. We can access add
or remove elements from the collections easily and it will preserve the order
of the elements.
var
mutableSet = mutableSetOf<Int>(6,10)
// adding
elements in set
mutableSet.add(2)
mutableSet.add(5)
for(item in
mutableSet){
println(item)
}
Map –
It is mutable so it supports functionalities like put, remove, clear,
etc.
var
mutableMap = mutableMapOf<Int,String>(1 to "Mahipal",2 to
"Nikhil",3 to "Rahul")
// we can modify
the element
mutableMap.put(1,"Praveen")
// add one more
element in the list
mutableMap.put(4,"Abhi")
for(item in
mutableMap.values){
println(item)
}
8.
How do you use the map, filter, and reduce functions
in Kotlin?
In Kotlin we can apply filter on collection using predicated
lambda. It will return true is predicates matches in that collection and return
false if it not match.
· These functions
don’t change the contents of the original collection or available for immutable
and mutable both.
- When filter() function
is called with a predicate, it returns the collection elements that match
the predicate.
· We can assign it
to a variable or chain the functions after filtering to operate the filtering
result.
val list = listOf("geeks","for","geeks","hello","world")
val longerThan4 = list.filter { it.length > 4 }
println(longerThan4)
9.
What is the use of the let function in Kotlin?
In Kotlin, the let function is a scope function that allows
you to execute a block of code within a specific context, providing:
1. Null safety
2. Contextual execution
3. Expression-oriented programming
Syntax:
object.let { block }
Key Features:
1. Null safety: let checks for nullability before executing
the block.
2. Contextual execution: let provides the object as a
parameter (it) within the block.
3. Expression-oriented: let returns the result of the block.
Example:
val name: String? = "John"
name?.let {
println("Hello, $it!") // Output: Hello, John!
}
Use Cases:
1. Null checks: Simplify null checks and avoid NPEs.
2. Contextual execution: Execute code within a
specific context.
3. Expression-oriented programming: Chain operations
and return values.
4. Scope control: Limit the scope of variables and
functions.
Common Patterns:
1. Null-safe calls:
val result = name?.let { process(it) }
1. Contextual initialization:
val person = Person().let {
it.name =
"John"
it.age = 30
it
}
1. Chaining operations:
val result = data?.let { processData(it) }?.let {
formatData(it) }
Other Scope Functions:
1. also (similar to let, but returns the original
object)(it)
2. apply (similar to let, but returns the original
object and allows modifications)
3. run (similar to let, but allows non-null receiver)
4. with (provides a context object without null
checks)
By mastering the let function and other scope functions,
you'll write more concise, null-safe, and expressive code in Kotlin.
10. What’s the use of
the lazy keyword in Kotlin?
In Kotlin, the lazy keyword is used to implement lazy
initialization, which delays the initialization of a property until its first
access.
Benefits:
1. Improved performance: Avoid unnecessary computations.
2. Reduced memory usage: Only allocate memory when needed.
3. Thread-safety: Ensures safe access in multi-threaded
environments.
Syntax:
val property: Type by lazy { initializer }
Key Features:
1. Lazy initialization: Initializes property only when
accessed.
2. Thread-safety: Ensures synchronized access.
3. Delegate: Uses a delegate to manage initialization.
Example:
class Person(private val name: String) {
val address: String
by lazy {
// Expensive
operation or database query
"123 Main
St"
}
}
fun main() {
val person =
Person("John")
println(person.address) // Initializes and prints "123 Main
St"
}
11. How does Kotlin handle immutability?
Kotlin provides strong support for immutability, encouraging
developers to write thread-safe, predictable, and maintainable code.
Immutable by Default
In Kotlin, all variables are immutable by default. The val
keyword declares a read-only variable, while var declares a mutable variable.
Immutable Data Structures
Kotlin's standard library provides immutable data structures,
such as:
1. List: Immutable lists (e.g., listOf())
2. Set: Immutable sets (e.g., setOf())
3. Map: Immutable maps (e.g., mapOf())
Immutable Classes
To create immutable classes, follow these guidelines:
1. Declare properties as val.
2. Use immutable data structures for properties.
3. Avoid mutable state (e.g., var properties).
4. Use constructor parameters to initialize properties.
Example:
data class Person(val name: String, val age: Int)
Data Classes
Kotlin's data classes provide a convenient way to create
immutable classes with:
1. Auto-generated equals(), hashCode(), and toString().
2. Immutable properties.
3. Copy functionality.
Best Practices
1. Prefer immutability by default.
2. Use val instead of var when possible.
3. Avoid shared mutable state.
4. Use immutable data structures and classes.
Benefits of Immutability
1. Thread-safety
2. Predictable behavior
3. Easier debugging
4. Improved code maintainability
12. Explain the concept of coroutines.
Coroutines
are a fundamental concept in Kotlin for asynchronous programming, allowing you
to write efficient, non-blocking, and concurrent code.
What
are Coroutines?
Coroutines
are lightweight threads that can suspend and resume execution, enabling
efficient asynchronous programming.
Key
Concepts:
1. Coroutine:
A function that can suspend and resume execution.
2. Suspend:
Pause coroutine execution, yielding control to other coroutines.
3. Resume:
Restart coroutine execution from where it was suspended.
4. Context:
The environment in which a coroutine runs.
Coroutine
Benefits:
1. Asynchronous
programming: Write non-blocking code.
2. Concurrent
execution: Run multiple coroutines simultaneously.
3. Efficient
resource usage: Minimize thread creation and switching.
4. Simplified
error handling: Use try-catch blocks.
Kotlin
Coroutine APIs:
1.
kotlinx.coroutines: The official Kotlin coroutine library.
2. CoroutineScope:
Defines the scope of coroutine execution.
3. launch:
Launches a coroutine.
4. async:
Creates a deferred coroutine.
5. suspend:
Suspends coroutine execution.
Coroutine
Builders:
1. launch:
Launches a coroutine.
2. async:
Creates a deferred coroutine.
3. runBlocking:
Blocks the current thread.
Coroutine
Scope:
1.
GlobalScope: Global coroutine scope.
2.
CoroutineScope: Custom coroutine scope.
Cancellation:
1. cancel():
Cancels a coroutine.
2.
CancellationException: Handles cancellation.
Coroutine
Exception Handling:
1.
try-catch: Catches exceptions.
2.
CoroutineExceptionHandler: Handles uncaught exceptions.
By mastering
coroutines, you'll write efficient, scalable, and maintainable asynchronous
code in Kotlin.
13. How does Kotlin handle variance
with generics?
Variance Basics
Variance determines how generic types relate to their
subtypes.
- Invariance: No subtype relationship (e.g.,
List<String> is not a subtype of List<Any>).
- Covariance: Subtype relationship preserves (e.g.,
List<String> is a subtype of List<Any>).
- Contravariance: Subtype relationship reverses (e.g.,
List<Any> is a subtype of List<String>).
Kotlin Variance Annotations
- out: Covariant (producer)
- in: Contravariant (consumer)
- No annotation: Invariant
Covariance (out)
- out T means T is produced, but not consumed.
- Enables subtype relationship.
Example:
class Producer<out T>(private val value: T) {
fun produce(): T =
value
}
fun main() {
val stringProducer:
Producer<String> = Producer("Hello")
val anyProducer:
Producer<Any> = stringProducer // Covariant
}
Contravariance (in)
- in T means T is consumed, but not produced.
- Reverses subtype relationship.
Example:
class Consumer<in T> {
fun consume(value:
T) {}
}
fun main() {
val anyConsumer:
Consumer<Any> = Consumer()
val stringConsumer:
Consumer<String> = anyConsumer // Contravariant
}
Invariant
- No annotation means T is both produced and consumed.
- No subtype relationship.
Example:
class MutableList<T> {
fun add(value: T)
{}
fun get(): T =
TODO()
}
fun main() {
val stringList:
MutableList<String> = MutableList()
// No subtype
relationship with MutableList<Any>
}
Best Practices
1. Use out for producers.
2. Use in for consumers.
3. Avoid invariant generic types.
By understanding variance in Kotlin, you'll create more
flexible and type-safe generic APIs.
14. Explain the concept of reified types
in Kotlin.
In Kotlin,
reified is a keyword used to enable inline functions to access type parameters
at runtime.
15. What’s the role of
the inline keyword?
In Kotlin,
the inline keyword is used to optimize performance by inlining functions at
compile-time. Function
inlining replaces a function call with the actual function body.
· Use inline for small, simple functions.
· Avoid inlining complex or large
functions.
· Use noinline for functions with
complex lambda
16. What’s the purpose of
the @JvmName annotation?
The @JvmName
annotation in Kotlin is used to specify a custom name for a function or
property when it is accessed from Java.
17. How do you handle checked exceptions
in Kotlin?
In Kotlin,
checked exceptions are handled using a combination of try-catch blocks and the
throws keyword.
- Checked
Exceptions: These are exceptions that are checked at compile-time. Examples
include IOException, SQLException.
- Unchecked
Exceptions: These are exceptions that are not checked at compile-time. Examples
include NullPointerException, IllegalArgumentException.
Handling
Checked Exceptions
1. Try-Catch
Block: Use a try-catch block to catch and handle the checked exception.
2. Throws
Keyword: Declare the checked exception using the throws keyword.
3. Rethrow
Exception: Rethrow the exception if you cannot handle it.
18. What’s the role of
the @JvmStatic annotation?
The
@JvmStatic annotation in Kotlin is used to specify that a companion object
function or property should be exposed as a static method or field in Java.
19. Explain the use of
the @JvmOverloads annotation.
The
@JvmOverloads annotation in Kotlin is used to generate multiple overloaded
functions in Java for a single Kotlin function with default parameter values.
20. What is the purpose of
the @file annotation?
The @file
annotation in Kotlin is used to specify that a class or function is intended to
be used as a script or executable file.
21. How do you write unit tests in
Kotlin?
22. What testing frameworks are commonly
used with Kotlin?
23. How do you use mock frameworks with
Kotlin?
24. what
is object class
object class is used as a singleton class. Object keyword we
used before class to make that class singleton class.
25. what
is the difference between const and val
const:-
const is a compile time constant.
Const always declare at the top level of class.
Const cannot apply to the var
Const only apply with val
We can have const variable inside class withing companion
object scope
Val:-
It is a runtime constant.
Val type variable by default is public and final.
Val type variable must initialization during creation
26. What
is generic class?
Generics in Kotlin are a powerful feature that allows you to
define reusable functions, classes, and interfaces that work with multiple
types.
Benefits
1. Type Safety: Generics ensure type safety by
preventing incorrect types.
2. Code Reusability: Generics enable code reusability
across multiple types.
3. Flexibility: Generics provide flexibility in
programming.
27. can
we declare const variable in last of class
No, const variable always reside on the top of the
class,interface
28. can
we have empty constructor in data class
No. at least one parameter require
29. what
is data class
Data class is a special type of class that provides a
concise way to represent simple data structures.
Features
·
Auto-generated getters and setters:
No need to define them manually.
·
toString() method: Automatically
generates a string representation.
·
equals() and hashCode() methods:
Automatically generates equality checks.
·
copy() function: Creates a copy of the
object with optional modifications.
·
componentN() functions: Allows
destructuring declarations.
30.
difference between thread and coroutines
Coroutine
|
Thread
|
Lightweight
|
heavy
|
Coroutines
allow for suspending and resuming execution at specific points, making it
easier to handle long-running tasks without blocking the main thread.
|
We can not
pause thread
|
coroutines
provide built-in exception handling mechanisms, making it easier to handle
and propagate exceptions within the coroutine context.
|
|
Both threads
and coroutines have their place in Kotlin Android development when it comes
to managing concurrency. Threads are a more traditional approach, while
coroutines provide a more modern and structured way to handle asynchronous
operations.
|
|
|
|
|
|
31. what
is Dispatcher.MAIN,IO and DEFAULT
In Kotlin Coroutines, Dispatchers are used to determine the thread or
threads that will execute coroutine code.
Three Main Dispatchers
. Dispatcher.Main:
- Executes coroutines on the
main thread.
- Suitable for UI-related
tasks.
- Used with Android's
lifecycleScope.
. Dispatcher.IO
- Executes coroutines on a
thread pool optimized for IO operations.
- Suitable for network
requests, database queries, and file operations.
. Dispatcher.Default:
- Executes coroutines on a
thread pool optimized for CPU-intensive tasks.
- Suitable for computationally
expensive operations.
Using Dispatchers:
GlobalScope.launch(Dispatcher.Main) {
// UI-related tasks
}
Switching Dispatchers:
GlobalScope.launch(Dispatcher.IO) {
// Perform IO operation
withContext(Dispatcher.Main) {
// Update UI
}
}
32. what
is invoke method
In Kotlin, the invoke() method is a special function that
allows an object to be called as a function.
Syntax:
class MyClass {
operator fun
invoke(): Unit {
// code to be
executed
}}
Example:
class Greeter {
operator fun
invoke(name: String) {
println("Hello, $name!")
}
}
fun main() {
val greeter =
Greeter()
greeter("John") // Prints "Hello, John!"}
33.
difference between data class and normal class
34.
why we r using data class for responses
35.
what is rx java
36. what
is extended function
an extension function is a function that adds functionality
to an existing class without modifying its source code.
37. what
is live data
LiveData is a lifecycle-aware data holder class in Android that allows
you to observe changes to data in a flexible and efficient manner.
Key Features:
1. Lifecycle-aware: Automatically manages observer subscriptions
based on lifecycle events.
2. Data holder: Holds a value of type T, which can be
observed.
3. Observable: Notifies observers when the held data changes.
Architecture:
1. LiveData: Holds data and notifies observers.
2. Observer: Listens to LiveData changes.
3. LifecycleOwner: Manages observer subscriptions.
// Create LiveData
val userData: MutableLiveData<User> = MutableLiveData()
// Set data
userData.value = User("John", 30)
// Observe data
userData.observe(this, Observer { user ->
// Handle data change
})
Types of LiveData:
1. MutableLiveData: Allows modifying the held data.
2. LiveData: Immutable, requires initial value.
38.
what is diff between interface and abstract
see from notebook
39.
how to call api
40.
how to use github and how to release build
41. type
of constructor in java
there are 2 types of constructor in Java
Parameterize constructor
Nonparameterized constructor
42. what
is singleton class
A singleton class is a design pattern that restricts a class
from instantiating multiple objects. It ensures that only one instance of the
class exists throughout the application's lifetime.
Kotlin Implementation:
object Singleton {
// Properties and
methods
}
Or
class Singleton private constructor() {
companion object {
private var
instance: Singleton? = null
fun
getInstance(): Singleton {
if
(instance == null) {
instance = Singleton()
}
return
instance!!
}
}
}
43. what
is lateinit and lazy in Kotlin
lateinit:-
by using lateinit
keyword we can declare a property that will be initialized later.It only
applicable to var not val.
lateinit var propertyName: Type
lazy:-
In Kotlin,
the lazy keyword is used to implement lazy initialization, which delays the
initialization of a property until its first access.
44. what
is retrofit
Retrofit is a popular, open-source HTTP client library for Android and
Java, developed by Square.
Key Features:
1. Simplifies HTTP requests and interactions.
2. Converts JSON responses to Java objects.
3. Supports various HTTP methods (GET, POST, PUT, DELETE, etc.).
4. Handles caching, authentication, and error handling.
Retrofit Architecture:
1. Interface: Define API endpoints and methods.
2. Retrofit instance: Create and configure Retrofit.
3. Converter: Convert JSON to Java objects.
4. Call: Execute HTTP requests.
45.
what is live data and mutable live data
46.
what is constraint layout