In this document you can find a series of basic examples showcasing the syntax and other aspects of functions, delegates, extension functions in Kotlin. This writeup deviates from what you might have learned with Java – you can treat this as brand-new knowledge.
Upon studying source code of Android apps written in Kotlin you will encounter examples like this:
kotlin
private val users: MutableLiveData<List<User>> by lazy { // See the by lazy property?
MutableLiveData().also{
//saves inside LiveData
loadUsers()
}
}
Read more about the also
operator
As you can see from the example above, this kind of syntax is quite different from Java and most likely looks a bit confusing at first. Let’s tackle this one piece at a time – so what does the … by lazy { }
do?
“Lazy” here refers to a lazy
property: the value inside the brackets gets computed only when it is needed, upon first access. For example the following block of code corresponding to lazyValue
is executed only when an attempt is made to access the value:
```kotlin val lazyValue: String by lazy { //Declare the var lazyValue using the by lazy{} keyword println(“computed once and then saved!”) //Initial the value is not set until lazyValue is called “Hello” //Subsequent calls use saved value }
fun main(){
println(lazyValue) // lazy keyword forces the initialization
println(lazyValue) // subsequent calls use the value stored from the lazy execution
}
``
The
lazyblock in the code above executes only once, the second time we access
lazyValueit will be read from the memory (upon the first execution it will be
saved`).
So with lazy
we can have more efficient code capable of delaying the execution of potentially heavy initialization blocks of code. It is especially suitable for properties that may or may not be accessed.
Read more about the lazy
operator
lateinit
keywordNormally, if a property is declared, but not initialized, your code won’t compile, and you will get a nastygram from the compiler. You can think of lateinit
as a way of telling the compiler that the given property will not be null and will initialize at some point, but not now:
```kotlin class Human { lateinit var name: String
fun name() {
print(name.length) //raises an error since name isn't initialized yet.
name = "John Doe"
print(name.length)
}
}
``
lateinitis useful for variables that hold handled to things like local databases, which take some time into start when the app runs. You can declare the handle as
lateinit, and then test if the handle is created or not before use. It's important to remember that trying to use a variable that is declared
lateinitwill raise an error, so make sure your variables are initialized before use. Also, remember that you can't use
lateiniton primitives like
Int,
Long,
Float,
Char`, etc.
Read more about the lateinit
keyword
```kotlin class DetailFragment : Fragment () { private lateinit var model: SharedViewModel
override fun onCreate(savedInstanceState: Bundle? ){
super.onCreate(savedInstanceState)
model = activity?.run {
ViewModelProviders.of(this).get(SharedViewModel::class.java)
} ?: throw Exception("Invalid Activity")
model.selected.observe(this, Observer<Item> { item ->
//This is a lambda function
//Do some stuff to update the UI
})
}
}
``
What about the functions that use
->` syntax? The example shown in the screenshot above is using a lambda function. You can think of lambda functions as functions that are anonymous, so they can’t be called directly (since they are unnamed), and for one-time use. Here are some example of how lambda functions can used in Kotlin:
```kotlin //Lets create some lamdba functions that can be passed as parameters //The first will take two Ints and add them together, returning the sum val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
//The second takes 2 Ints, multiplies them, and returns the product val mult = { x: Int, y: Int -> x * y }
/* This function takes three params: two Ints, and a Function. The function parameter passed determines the type of math applied / fun arithmetic ( i:Int,j:Int, foo: (i:Int,j:Int)->Int): Int{ return foo(i,j) }
fun main(){ println(arithmetic(2,3,sum)) // Add 2 and 3 println(arithmetic(2,3,mult)) // Mulitply 2 by 3
//In this case, we are creating a lambda function, to divide the Ints, within the call the arithmetic println(arithmetic(4,2,{x,y -> x / y})) // Divide 4 by 2 }
/ Output would be: 5 6 2 / ```
The example above shows how Kotlin can treat functions as parameters and pass them to other functions. In this particular case we have a function called arithmetic
that takes three parameters: two ints and a function. The function that is received as a parameter determines the actual arithmetic operation to be performed. In our example there are three possibilities: summation, multiplication and division. All three of the operations have dedicated functions that are passed to arithmetic
and then executed. Note the differences in the syntax used to define the functions. The differences in syntax show the flexibility of Kotlin in defining functions. The last example (division) is using a lambda function — it is not using a variable to refer to its body, the function is simply defined on the spot inside the place where the parameter referring to the function would go.
Read more about lambda functions
What about the also
block (and other similar blocks)? What is it and why use it? See the docs..
And use the following guideline when it comes to choosing various scoping functions:
let
let
apply
run
run
also
with