Values and Mutability In Kotlin: Getting Started

In this Values and Mutability tutorial, you’ll learn how to declare mutable, immutable, constant, late/lazily initialized, static & inline values. By Gabriela Kordić.

Leave a rating/review
Download materials
Save for later
Share

Values and mutability are features all programming languages need to provide. Have you ever had to declare a counter field or save an index of the last selected item in a list? Or did you need to save a license key for a third-party library such as Google Maps?

If the answer is yes, you most likely wondered if you should define those values inside or outside a class and which keywords you need to use. Considering Kotlin has several ways to define values across code, you probably had a hard time finding the best suitable solution.

Finally, here’s a tutorial to address all your doubts! :]

There are three possible ways of creating values in Kotlin — by using var, val and const val before a value name. In this tutorial, you’ll implement them and discover more about the differences between them.

More specifically, you’ll learn:

  • How to declare mutable values, also known as variables, and where to use them
  • How to declare immutable values and where to use them
  • The difference between lazy initialization and late initialization
  • The way to declare a constant and where to use it
  • What a companion object is
  • The difference between static values and inline values
Note: This tutorial assumes a basic knowledge of Android Studio and Kotlin. If you aren’t familiar with Android Studio or you haven’t installed it yet, refer to our Beginning Android Development tutorials.

Getting Started

Download the starter project by clicking the Download Materials button at the top or bottom of the tutorial.

In this tutorial, you’ll use the Tempco app. Tempco is a single-screen app for converting temperature values between Fahrenheit, Celsius and Kelvin measurement units.

Open the project in Android Studio. Build and run on a device to see how the app looks. Right now, you’re not able to experiment with conversions, but don’t worry, because you’ll implement all you need to use the app!

The main screen of Tempco.

The app contains a ConstraintLayout with one EditText for inserting the desired temperature value, two Spinner widgets for the initial and final measurement unit, and a TextView for displaying a result. Every element of the layout has a TextView above itself with instructions for use. It’s enough to interact with spinners to see the calculated result.

The app is quite simple, because the focus of the tutorial will be on values and declarations, instead of the Android UI!

Declaring Values

The first step for declaring values is to determine whether to declare it with val or var. What’s the real difference though?

First of all, a var is also known as a variable, something that changes over time, whereas a val is also known as a value, something that doesn’t change over time.

Both variables and values point to values and the terminology can be confusing, but values mean data in this case, and not a property you declare.

That being said, the keyword var is for mutable or non-final data, also knows as variables. You declare variables only if you’ll change the data it points to or the object it references to later.

Meanwhile, the keyword val defines immutable or final values and you can’t change their reference. It similar to the final variable in Java — it’s read-only.

It’s easy to differentiate between var and val, isn’t it? The terminology might be a bit confusing, but you’ll get the hang of it in no time! Now you’ll practice the implementation.

Defining Immutable Values

Open MainViewModel.kt and look for calculate(). This function returns the result of temperature conversions. Add the following line to the top of it:

val temperatureValue: Double = value.toDouble()

Here, you’re defining an immutable value using val. You’re using immutability because the variable is only used as a parameter in conversion — you won’t change it. Then, you’re setting up a return type as Double and assigning the real value, which the user types in EditText.

Now, use this new value in calculate(). Since you already have conversion and finalUnit declared, use them and add the following code below finalUnit:

conversionHelper.getConvertedValue(
  conversion,
  temperatureValue,
  finalUnit,
  ::onSuccess,
  ::onError
)

In this code, you’re using three values and two lambdas using getConvertedValue(). This function uses conversion to find the right formula for the result temperature.

If the calculation succeeds, the system calls onSuccess() and sends back the result. Otherwise, it calls onError() and sends back a String resource to inform the user.

In case you’re wondering if you could use a variable for temperatureValue, the answer is: There’s no need. It’s only used inside calculate(), and you don’t change it.

Defining Mutable Values

Now that you’ve mastered immutability, here’s a mutability task for you! In the same file, replace unitArray with the following code:

var unitArray: Array<String> = emptyArray()

In this line, you declared a variable using var. You set its name to unitArray and the type as an Array of String items, with the default value of an emptyArray().

But why is this a variable? Right now, unitArray is empty because of its default value, but to calculate the result, unitArray needs to contain all the available units.

Consequently, you need to assign an appropriate array of units, and you use a variable to be able to change its value.

There are two reasons why you needed to assign an empty default array. First, the needed array exists in strings.xml. And to use resources, you need a Context. At this place in code, you don’t have access to a Context, as it’s an Android dependency and you shouldn’t mix your business logic with the Android platform.

Second, variables need to be initialized straight away, be abstract, or use lateinit var, which you’ll learn about later.

Data Types and Default Values

When using variables, you need to assign the default value. Otherwise, Android Studio throws an error that the variable either needs to be initialized or it needs to be abstract.

Try this out. Remove the default value of unitArray. Your code will look like this:

var unitArray: Array<String>

You can see the error to set the default value.

The error to define a default value for variable of a primitive data type.

Note: Detailed information about data types is outside the scope of this tutorial. You can read about this in the Kotlin documentation.

Surely you’re wondering what to do if you don’t know which values to set by default, or what to do if you don’t have all the parameters you need at the moment. In the next section, you’ll learn what to do in such situations!