Chapter 12. Connecting Our Kotlin to the UI and Nullability
By the end of this chapter, the missing link between our Kotlin code and our XML layouts will be fully revealed, leaving us with the power to add all kinds of widgets and UI features to our layouts as we have done before, but this time we will be able to control them through our code.
In this chapter, we will take control of some simple UI elements, such as Button
and TextView
, and, in the next chapter, we will take things further and manipulate a whole range of UI elements.
To enable us to understand what is happening, we need to find out a bit more about the memory in an app, and two areas of it in particular – the Stack and the Heap.
In this chapter, we will cover the following topics:
Android UI elements are classes
Garbage collection
Our UI is on the Heap
More polymorphism
Nullability – val and var revisited
Casting to different types
Prepare to make your UI come to life.
All the Android UI elements are classes too
When our app is run and the setContentView
function is called from the onCreate
function, the layout is inflated from the XML UI, and is loaded into memory as usable objects. They are stored in a part of the memory called the Heap.
But where is this Heap place? We certainly can't see the UI instances in our code. And how on earth do we get our hands on them?
The operating system inside every Android device takes care of memory allocation to our apps. In addition, it stores different types of variables in different places.
Variables that we declare and initialize in functions are stored in an area of memory known as the Stack. We already know how we can manipulate variables on the Stack with straightforward expressions. So, let's talk about the Heap some more.
Note
Important fact: all objects of classes are reference type variables and are just references to the actual objects that are stored on the Heap – they are not the actual objects.
Think of the...
An interface is like a class. Phew! Nothing complicated here then. But, it's like a class that is always abstract, and only has abstract functions.
We can think of an interface as an entirely abstract class, with all its functions and properties being abstract. When a property is abstract, it does not hold a value. It has no backing field for the property. However, when another class implements (uses) the interface, it must override the property, and therefore provide the backing field for storing a value.
Simply put, interfaces are stateless classes. They provide an implementation template without any data.
OK, so you can just about wrap your head round an abstract class, because at least it can pass on some functionality in its functions and some state in its properties that are not abstract and serve as a polymorphic type.
But, seriously, this interface seems a bit pointless. Let's look at the simplest possible example of an interface, then we can discuss it further.
To...
Using buttons and TextView widgets from our layout with a little help from interfaces
To follow along with this project, create a new Android Studio project, call it Kotlin Meet UI
, and choose the Empty Activity template. You can find the code and the XML layout code in the Chapter12
/Kotlin Meet UI
folder.
First, let's build a simple UI by observing the following steps:
In the editor window of Android Studio, switch to activity_main.xml
and make sure you are on the Design tab.
Delete the auto-generated TextView
, the one that reads "Hello world!".
Add a TextView widget to the top-center of the layout.
Set its text property to 0
, its id
property to txtValue
, and its textSize
to 40sp
. Pay careful attention to the case of the id
value. It has an uppercase V
.
Now, drag and drop six buttons on to the layout so that it looks a bit like the following diagram. The exact layout isn't important:
When the layout is how you want it, click the Infer Constraints button to constrain all the UI items.
Double left...
Nullability – val and var revisited
When we declare an instance of a class with val
it does not mean we cannot change the value held in the properties. What determines whether we can reassign the values held by the properties is whether the properties themselves are val
or var
.
When we declare an instance of a class with val
, it just means we cannot reassign another instance to it. When we want to reassign to an instance, we must declare it with var
. Here are some examples:
In the preceding hypothetical code, an instance called someInstance
is declared, and it is of the SomeClass
type. It is declared as val
. The three lines of code that follow suggest that, if its properties were declared with var
we can change those properties, but, as we have already learned, when...
In this chapter, we finally had some real interaction between our code and our UI. It turns out that every time we add a widget to our UI, we are adding a Kotlin instance of a class that we can access with a reference in our code. All these objects are stored in a separate area of memory called the Heap – along with any instances of classes of our own.
We are now in a position where we can learn about and do cool things with some of the more interesting widgets. We will look at loads of them in the next chapter, Chapter 13, Bringing Android Widgets to Life, and we will also keep introducing new widgets throughout the rest of the book.