Saturday, 21 September 2024

Kotlin Jetpack Compose

In this i have created one main layout with green background ,and place a text inside for loop,added scrollView in Column

 @Composable

fun MainLayout() {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Green)
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
) {
for (i in 1..5)
Text(text = "Supriya")
}
}
}
2. Here we can create LazyColumn to have scrool automatically,
no need to add scrll attributes. 
@Composable
fun MainLayout() {
LazyColumn( modifier = Modifier
.background(Color.Magenta),
content = {
item {
for (i in 1..200)
Text(text = "Android"
, modifier = Modifier
.fillMaxWidth()
.padding(30.dp))
}
}
)
}


3. Play with Box-Layout it is same like FrameLayout. added 3
textview and one button with click amd showing Toast popup.
@Composable
fun MainLayout() {
Box(
modifier = Modifier
.fillMaxSize()
.padding(20.dp),
contentAlignment = Alignment.Center
) {
Text(
text = "Supriya",
color = Color.Red,
modifier = Modifier.align(Alignment.TopCenter)
)
Text(text = "Ankit", color = Color.Green, modifier = Modifier.align(Alignment.Center))
Text(
text = "Saurabh",
color = Color.Magenta,
modifier = Modifier.align(Alignment.BottomCenter)
)

Button(
onClick = {
Toast.makeText(this@MainActivity, "Button Click", Toast.LENGTH_LONG).show()
},
modifier = Modifier
.align(Alignment.CenterEnd)) {
Text(text = "ClickMe")

}
}
}








4. CardLayout in jetpack Compose
@Composable
fun MainLayout() {
Card(modifier = Modifier
.padding(horizontal = 8.dp, vertical = 10.dp)
.fillMaxWidth(),
elevation = CardDefaults.cardElevation(8.dp)) {
Image(
painter = painterResource(id = R.drawable.img_1),
contentDescription = null,
modifier = Modifier
.padding(8.dp)
.width(100.dp)
.height(100.dp)
.clip(RoundedCornerShape(CornerSize(4.dp)))
)
Text(text = "Supriya", modifier = Modifier
.align(Alignment.End)
.fillMaxWidth())
}
}

5. Change status bar color:
res->values->themes.xml
<resources>
<
style name="Theme.BAsicCompose1" parent="android:Theme.Material.Light.NoActionBar">
<item name="android:statusBarColor">@color/lightPurple</item>
</
style>
</
resources>
res->values->colors.xml
<color name="lightPurple">#FFD0BCFF</color>

Friday, 20 September 2024

Kotlin Most Asking interview Question.

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 trycatch, 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

 

how to change status bar color in jectpack compose.

 Step1: Go to MainActivity and do following: enableEdgeToEdge ( statusBarStyle = SystemBarStyle .light( Color . Green .h...