Kotlin Programming By Example

4.8 (4 reviews total)
By Iyanu Adelekan
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies
  1. The Fundamentals

About this book

Kotlin greatly reduces the verbosity of source code. With Google having announced their support for Kotlin as a first-class language for writing Android apps, now's the time learn how to create apps from scratch with Kotlin

Kotlin Programming By Example takes you through the building blocks of Kotlin, such as functions and classes. You’ll explore various features of Kotlin by building three applications of varying complexity. For a quick start to Android development, we look at building a classic game, Tetris, and elaborate on object-oriented programming in Kotlin. Our next application will be a messenger app, a level up in terms of complexity. Before moving onto the third app, we take a look at data persistent methods, helping us learn about the storage and retrieval of useful applications. Our final app is a place reviewer: a web application that will make use of the Google Maps API and Place Picker.

By the end of this book, you will have gained experience of of creating and deploying Android applications using Kotlin.

Publication date:
March 2018
Publisher
Packt
Pages
500
ISBN
9781788474542

 

Chapter 1. The Fundamentals

Learning a programming language is a daunting experience for many people, and not one that most individuals generally choose to undertake. As you have chosen to pick up this book, I assume that you have an interest in learning the Kotlin programming language and perhaps even becoming an expert at it someday. As a consequence, permit me to congratulate you on taking a bold step toward learning this language.

Regardless of the problem domain that you may wish to build solutions for, be it application development, networking, or distributed systems, Kotlin is a good choice for the development of systems to achieve the required solutions. In other words, a developer can't go wrong with learning Kotlin. At this point, a proper introduction to the Kotlin language is required.

Kotlin is a strongly-typed, object-oriented language that runs on the Java Virtual Machine (JVM) and can be used to develop applications in numerous problem domains. In addition to running on the JVM, Kotlin can be compiled to JavaScript, and as such, is an equally strong choice for developing client-side web applications. Kotlin can also be compiled directly into native binaries that run on systems without a virtual machine via Kotlin/Native. The Kotlin programming language was primarily developed by JetBrains – a company based in Saint Petersburg, Russia. The developers at JetBrains are the current maintainers of the language. Kotlin was named after Kotlin island – an island near Saint Petersburg.

Kotlin was designed to be used to develop industrial-strength software in many domains, but has seen the majority of its use come from the Android ecosystem. At the time of writing, Kotlin is one of the three languages that have been declared by Google as an official language for Android. Kotlin is syntactically similar to Java. As a matter of fact, it was designed to be a better alternative to Java. As a consequence, there are numerous significant advantages to using Kotlin instead of Java in software development.

In this chapter, you will learn the following:

  • The installation of Kotlin
  • The fundamentals of the Kotlin programming language
  • Installing and setting up Android Studio
  • Gradle
  • The fundamentals of the web
 

Getting started with Kotlin


In order to develop the Kotlin program, you will first need to install the Java Runtime Environment (JRE) on your computer. The JRE can be downloaded prepackaged along with a Java Development Kit (JDK). For the sake of this installation, we will be using the JDK.

The easiest way to install a JDK on a computer is to utilize one of the JDK installers made available by Oracle (the owners of Java). There are different installers available for all major operating systems. Releases of the JDK can be downloaded from http://www.oracle.com/technetwork/java/javase/downloads/index.html:

Java SE web page

Clicking on the JDK download button takes you to a web page where you can download the appropriate JDK for your operating system and CPU architecture. Download a JDK suitable for your computer and continue to the next section:

JDK download page

JDK installation

In order to install the JDK on your computer, check out the necessary installation information from the following sections, based on your operating system.

Installation on Windows

The JDK can be installed on Windows in four easy steps:

  1. Double-click the downloaded installation file to launch the JDK installer.
  2. Click the Next button in the welcome window. This action will lead you to a window where you can select the components you want to install. Leave the selection at the default and click Next.
  1. The following window prompts the selection of the destination folder for the installation. For now, leave this folder as the default (also take note of the location of this folder, as you will need it in a later step). Click Next.
  2. Follow the instructions in the upcoming windows and click Next when necessary. You may be asked for your administrator's password, enter it when necessary. Java will be installed on your computer.

After the JDK installation has concluded, you will need to set the JAVA_HOME environment variable on your computer. To do this:

  1. Open your Control Panel.
  2. Select Edit environment variable.
  3. In the window that has opened, click the New button. You will be prompted to add a new environment variable.
  4. Input JAVA_HOME as the variable name and enter the installation path of the JDK as the variable value.
  5. Click OK once to add the environment variable.

Installation on macOS

In order to install the JDK on macOS, perform the following steps:

  1. Download your desired JDK .dmg file.
  2. Locate the downloaded .dmg file and double-click it.
  3. A finder window containing the JDK package icon is opened. Double-click this icon to launch the installer.
  4. Click Continue on the introduction window.
  5. Click Install on the installation window that appears.
  6. Enter the administrator login and password when required and click Install Software.

The JDK will be installed and a confirmation window displayed.

Installation on Linux

Installation of the JDK on Linux is easy and straightforward using apt-get:

  1. Update the package index of your computer. From your terminal, run:
      sudo apt-get update
  1. Check whether Java is already installed by running the following:
      java -version
  1. You'll know Java is installed if the version information for a Java install on your system is printed. If no version is currently installed, run:
      sudo apt-get install default-jdk

That's it! The JDK will be installed on your computer.

Compiling Kotlin programs

Now that we have the JDK set up and ready for action, we need to install a means to actually compile and run our Kotlin programs.

Kotlin programs can be either compiled directly with the Kotlin command-line compiler or built and run with the Integrated Development Environment (IDE).

Working with the command-line compiler

The command-line compiler can be installed via Homebrew, SDKMAN!, and MacPorts. Another option for setting up the command-line compiler is by manual installation.

Installing the command-line compiler on macOS

The Kotlin command-line compiler can be installed on macOS in various ways. The two most common methods for its installation on macOS are via Homebrew and MacPorts.

Homebrew

Homebrew is a package manager for the macOS systems. It is used extensively for the installation of packages required for building software projects. To install Homebrew, locate your macOS terminal and run:

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

You will have to wait a few seconds for the download and installation of Homebrew. After installation, check to see whether Homebrew is working properly by running the following command in your terminal:

brew -v

If the current version of Homebrew installed on your computer is printed out in the terminal, Homebrew has been successfully installed on your computer.

After properly installing Homebrew, locate your terminal and execute the following command:

brew install kotlin

Wait for the installation to finish, after which you are ready to compile Kotlin programs with the command-line compiler.

MacPorts

Similar to HomeBrew, MacPorts is a package manager for macOS. Installing MacPorts is easy. It can be installed on a system by:

  1. Installing Xcode and the Xcode command-line tools.
  2. Agreeing to the Xcode license. This can be done in the terminal by running xcodebuild -license.
  3. Installing the required version of MacPorts.

MacPort versions can be downloaded from https://www.macports.org/install.php.

Once downloaded, locate your terminal and run port install kotlin as the superuser:

sudo port install kotlin

Installing the command-line compiler on Linux

Linux users can easily install the command-line compiler for Kotlin with SDKMAN!

SDKMAN!

This can be used to install packages on Unix-based systems such as Linux and its various distributions, for example, Fedora and Solaris. SDKMAN! can be installed in three easy steps:

  1. Download the software on to your system with curl. Locate your terminal and run:
      curl -s "https://get.sdkman.io" | bash
  1. After you run the preceding command, a set of instructions will come up in your terminal. Follow these instructions to complete the installation. Upon completing the instructions, run:
      source "$HOME/.sdkman/bin/sdkman-init.sh"
  1. Run the following:
      sdk version

If the version number of SDKMAN! just installed is printed in your terminal window, the installation was successful.

Now that we have SDKMAN! successfully installed on our system, we can install the command-line compiler by running:

      sdk install kotlin

Installing the command-line compiler on Windows

In order to use the Kotlin command-line compilers on Windows:

  1. Download a GitHub release of the software from https://github.com/JetBrains/kotlin/releases/tag/v1.2.30
  2. Locate and unzip the downloaded file
  1. Open the extracted kotlinc\bin folder
  2. Start the command prompt with the folder path

You can now make use of the Kotlin compiler from your command line.

Running your first Kotlin program

Now that we have our command-line compiler set up, let's try it out with a simple Kotlin program. Navigate to your home directory and create a new file named Hello.kt. All Kotlin files have a .kt extension appended to the end of the filename.

Open the file you just created in a text editor of your choosing and input the following:

// The following program prints Hello world to the standard system output.
fun main (args: Array<String>) {
  println("Hello world!")
}

Save the changes made to the program file. After the changes have been saved, open your terminal window and input the following command:

kotlinc hello.kt -include-runtime -d hello.jar

The preceding command compiles your program into an executable, hello.jar. The -include- runtime flag is used to specify that you want the compiled JAR to be self-contained. By adding this flag to the command, the Kotlin runtime library will be included in your JAR. The -d flag specifies that, in this case, we want the output of the compiler to be called.

Now that we have compiled our first Kotlin program, we need to run it—after all, there's no fun in writing programs if they can't be run later on. Open your terminal, if it's not already open, and navigate to the directory where the JAR was saved to (in this case, the home directory).  To run the compiled JAR, perform the following:

java -jar hello.jar

After running the preceding command, you should see Hello world! printed on your display. Congratulations, you have just written your first Kotlin program!

Writing scripts with Kotlin

As previously stated, Kotlin can be used to write scripts. Scripts are programs that are written for specific runtime environments for the common purpose of automating the execution of tasks. In Kotlin, scripts have the .kts file extension appended to the file name.

Writing a Kotlin script is similar to writing a Kotlin program. In fact, a script written in Kotlin is exactly like a regular Kotlin program! The only significant difference between a Kotlin script and regular Kotlin program is the absence of a main function.

Create a file in a directory of your choosing and name it NumberSum.kts. Open the file and input the following program:

val x: Int = 1
val y: Int = 2
val z: Int = x + y
println(z)

As you've most likely guessed, the preceding script will print the sum of 1 and 2 to the standard system output. Save the changes to the file and run the script:

kotlinc -script NumberSum.kts

Note

A significant thing to take note of is that a Kotlin script does not need to be compiled.

Using the REPL

REPL is an acronym that stands for Read–Eval–Print Loop. An REPL is an interactive shell environment in which programs can be executed with immediate results given. The interactive shell environment can be invoked by running the kotlinc command without any arguments.

Note

The Kotlin REPL can be started by running kotlinc in your terminal.

If the REPL is successfully started, a welcome message will be printed in your terminal followed by >>> on the next line, alerting us that the REPL is awaiting input. Now you can type in code within the terminal, as you would in any text editor, and get immediate feedback from the REPL. This is demonstrated in the following screenshot:

Kotlin REPL

In the preceding screenshot, the 1 and 2 integers are assigned to x and y, respectively. The sum of x and y is stored in a new z variable and the value held by z is printed to the display with the print() function.

Working with an IDE

Writing programs with the command line has its uses, but in most cases, it is better to use software built specifically for the purpose of empowering developers to write programs. This is especially true in cases where a large project is being worked on.

An IDE is a computer application that hosts a collection of tools and utilities for computer programmers for software development. There are a number of IDEs that can be used for Kotlin development. Out of these IDEs, the one with the most comprehensive set of features for the purpose of developing Kotlin applications is IntelliJ IDEA. As IntelliJ IDEA is built by the creators of Kotlin, there are numerous advantages in using it over other IDEs, such as an unparalleled feature set of tools for writing Kotlin programs, as well as timely updates that cater to the newest advancements and additions to the Kotlin programming language.

Installing IntelliJ IDEA

IntelliJ IDEA can be downloaded for Windows, macOS, and Linux directly from JetBrains' website: https://www.jetbrains.com/idea/download. On the web page, you are presented with two available editions for download: a paid Ultimate edition and a free Community edition. The Community edition is sufficient if you wish to run the programs in this chapter. Select the edition you wish to download:

IntelliJ IDEA download page

Once the download is complete, double-click on the downloaded file and install it on your operating system as you would any program.

Setting up a Kotlin project with IntelliJ

The process of setting up a Kotlin project with IntelliJ is straightforward:

  1. Start the IntelliJ IDE application.
  2. Click Create New Project.
  1. Select Java from the available project options on the left-hand side of the newly opened window.
  2. Add Kotlin/JVM as an additional library to the project.
  3. Pick a project SDK from the drop-down list in the window.
  4. Click Next.
  5. Select a template if you wish to use one, then continue to the next screen.
  6. Provide a project name in the input field provided. Name the project HelloWorld for now.
  7. Set a project location in the input field.
  8. Click Finish.

Your project will be created and you will be presented with the IDE window:

To the left of the window, you will immediately see the project view. This view shows the logical structure of your project files.

Two folders are present. These are:

  • .idea: This contains IntelliJ's project-specific settings files.
  • src: This is the source folder of your project. You will place your program files in this folder.

Now that the project is set up, we will write a simple program. Add a file named hello.kt to the source folder (right-click the src folder, select New | Kotlin File/Class, and name the file hello). Copy and paste the following code into the file:

fun main(args: Array<String>) {
println("Hello world!")
}

To run the program, click the Kotlin logo adjacent to the main function and select Run HelloKt:

The project will be built and run, after which, Hello world! will be printed to the standard system output.

 

The fundamentals of the Kotlin programming language


Now that we have set up our development environment and our IDE of choice, it is time to explore Kotlin. We will start by diving into the basics of the language and progress into more advanced topics, such as object-oriented programming (OOP). 

Kotlin basics

In this section, we will explore the basics of Kotlin—the building blocks, if you will. We will start by discussing variables.

 

Variables

A variable is an identifier for a memory location that holds a value. A simpler way to describe a variable is an identifier that holds a value. Consider the following program:

fun main(args: Array<String>) {
  var x: Int = 1
}

The preceding x is a variable and the value it holds is 1. More specifically, x is an integer variable. The x is referred to as an integer variable because x has been defined to have the Int data type. As such, the x variable can only hold an integer value. To be more accurate, we say that x is an instance of the Int class. At this point, you must be wondering what the words instance and class mean in this context. All will be revealed in due time. For now, let's focus on the topic of variables.

When defining a variable in Kotlin, we make use of the var keyword. This keyword specifies that the variable is mutable in nature. Thus, it can be changed. The data type of the declared variable comes after a semicolon that follows the variable's identifier. It is important to note that the data type of a variable need not be explicitly defined. This is because Kotlin supports type inference—the ability to infer types of objects upon definition. We might as well have written the definition of our x variable as:

var x = 1

The outcome of the definition would be the same. A semicolon can be added to the end of the line of our variable definition but, similar to languages like JavaScript, it is not required:

var x = 1 // I am a variable identified by x and I hold a value of 1
var y = 2 // I am a variable identified by y and I hold a value of 2
var z: Int = x + y // I am a variable identified by z and I hold a value of 3

If we don't want the values of our variables to change over the course of the execution of our program, we can do so by making them immutable. Immutable variables are defined with the val keyword, as follows:

val x = 200
Variable scope

The scope of a variable is the region of a program where the variable is of consequence. In other words, the scope of a variable is the region of a program in which the variable can be used. Kotlin variables have block scope. Therefore, the variables can be utilized in all regions that the block they were defined in covers:

fun main(args: Array<String>) {
  // block A begins
  var a = 10
  var i = 1

  while (i < 10) {
    // block B begins
    val b = a / i
    print(b)
    i++
  }
  print(b) // Error occurs: variable b is out of scope
}

In the preceding program, we can directly observe the effects of block scope by taking a look at the two blocks. The definition of a function opened a new block. We have labeled to this block as B in our example. Within A, the a and i variables were declared. As such, the scope of the a and i variables exists within A.

A while loop was created within A, and as such, a new B block was opened. Loop declarations mark the beginning of new blocks. Within B, a b value is declared. The b value exists in the B scope and can't be used outside its scope. As such, when we attempt to print the value held by b outside the B block, an error will occur.

One thing worth noting is that the a and i variables can still be utilized within the B block. This is because B exists within the scope of A.

Local variables

These are variables that are local to a scope. The a, i, and b variables in our previous example are all local variables.

Operands and operators

An operator is the part of an instruction that specifies the value to be operated on. An operator also carries out a specific operation on its operands. Examples of operators are +, -, *, /, and %. Operators can be categorized based on the type of operations carried out and the number of operands acted upon by the operator.

Based on the type of operations carried out by the operator, we can classify operators into:

  • Relational operators
  • Assignment operators
  • Logical operators
  • Arithmetic operators
  • Bitwise operators

Operator type

Examples

Relational operators

>, <, >=, <=, ==

Assignment operators

+=, -=, *=, /=, =

Logical operators

&&, ||, !

Arithmetic operators

+, -, *, /

Bitwise operators

and(bits), or(bits), xor(bits), inv(), shl(bits), shr(bits), ushr(bits)

 

Based on the number of operands acted upon, we have two main types of operators in Kotlin:

  • Unary operators
  • Binary operators

Operator type

Description

Examples

Unary operator

Requires only one operand

!, ++, - -

Binary operator

Requires two operands

+, -, *, /, %, &&, ||

Types

The type of a variable, with respect to its value space, is the set of possible values that the variable can possess. In many cases, it is useful to be able to explicitly specify the type of value you want to be held by a variable being declared. This can be done using a data type.

Some important types in Kotlin are:

  • Int
  • Float
  • Double
  • Boolean
  • String
  • Char
  • Array
Int

This type represents a 32-bit signed integer. When a variable is declared with this type, the value space of the variable is the set of integers, that is, the variable can only hold integer values. We have seen the use of this type several times in our examples so far. The Int type can hold integer values within the range of -2,147,483,648 to 2,147,483,647.

Float

This type represents a single precision 32-bit floating-point number. When used with a variable, this type specifies that the variable can only hold floating-point values. Its range is approximately ±3.40282347E+38F (6-7 significant decimal digits):

var pi: Float = 3.142
Double

This type represents a double precision 64-bit floating-point number. Similar to the Float type, this type specifies that the variable being declared holds floating-point values. An important difference between the Double and Float types is that Double can hold numbers across a much larger range without overflow. Its range is approximately ±1.79769313486231570E+308 (15 significant decimal digits):

var d: Double = 3.142
Boolean

The true and false logical truth values are represented by the Boolean type:

var t: Boolean = true
var f: Boolean = false

Boolean values are operated upon by the &&, ||, and ! logical operators:

Operator name

Operator

Description

Operator type

Conjunction

&&

Evaluates to true when two of its operands are true, otherwise evaluates to false.

Binary

Disjunction

||

Evaluates to true when at least one operand is true, otherwise evaluates to false.

Binary

Negation

!

Inverts the value of its Boolean operand.

Unary

String

A string is a sequence of characters. In Kotlin, strings are represented by the string class. Strings can be easily written by typing out a sequence of characters and surrounding it with double quotation marks:

val martinLutherQuote: String = "Free at last, Free at last, Thank God almighty we are free at last."
Char 

This type is used to represent characters. A character is a unit of information that roughly corresponds to a grapheme, or a grapheme-like unit or symbol. In Kotlin, characters are of the Char type. Characters in single quotes in Kotlin, such as a, $, %, and &, are all examples of characters:

val c: Char = 'i' // I am a character

Recall we mentioned earlier that a string is a sequence of characters:

var c: Char
val sentence: String = "I am made up of characters."

for (character in sentence) {
c = character // Value of character assigned to c without error
println(c)
}
Array

An array is a data structure consisting of a set of elements or values with each element possessing at least one index or key. Arrays are very useful in storing collections of elements you wish to utilize later on in a program.

In Kotlin, arrays are created using the arrayOf() library method. The values you wish to store in the array are passed in a comma-separated sequence:

val names = arrayOf("Tobi", "Tonia", "Timi")

Each array value has a unique index that both specifies its position in the array and can be used to retrieve the value later on. The set of indices in an array starts with the index, 0, and progresses with an increment of 1.

The value held in any given index position of an array can be retrieved by either calling the Array#get() method or by using the [] operation:

val numbers = arrayOf(1, 2, 3, 4)
println(numbers[0]) // Prints 1
println(numbers.get(1)) // Prints 2

At any point in time, the value at a position of an array can be changed:

val numbers = arrayOf(1, 2, 3, 4)
println(numbers[0]) // Prints 1
numbers[0] = 23
println(numbers[0]) // Prints 23

You can check the size of an array at any time with its length property:

val numbers = arrayOf(1, 2, 3, 4)
println(numbers.length) // Prints 4

Functions

A function is a block of code that can be defined once and reused any number of times. When writing programs, it is best practice to break up complex programmatic processes into smaller units that perform specific tasks. Doing this has many advantages, some of which are:

  • Improving code readability: It is much easier to read programs that have been broken down into functional units. This is because the scope of the code to be understood at any given point in time is reduced when functions are utilized. The majority of the time, a programmer needs to only write or adjust a section of a large code base. When functions are utilized, the context of the program that needs to be read to ameliorate program logic is restricted to the body of the function in which the logic is written.
  • Improving the maintainability of a code base: The use of functions in a code base makes it easy to maintain programs. If a change needs to be made to a particular program feature, many times it is as easy as adjusting a function in which the feature has been created.
Declaring functions

Functions are declared with the fun keyword. The following is a simple function definition:

fun printSum(a: Int, b: Int) {
  print(a + b)
}

The function simply prints the sum of two values that have been passed as arguments to it. Function definitions can be broken down into the following components:

  • A function identifier: The identifier of a function is the name given to it. An identifier is required to refer to the function if we wish to invoke it later on in a program. In the preceding function declaration, printSum is the identifier of the function.
  • A pair of parentheses containing a comma-separated list of the arguments being passed as values to the function: Values passed to a function are called arguments of the function. All arguments passed to the function must have a type. The type definition of an argument follows a semicolon placed after the argument name.
  • A return type specification: Return types of functions are specified similarly to the way the types of variables and properties are. The return type specification follows the last parenthesis and is done by writing the type after a semicolon.
  • A block containing the body of the function.

Observing the preceding function, it may appear that it has no return type. This is not true, the function has a return type of Unit. A unit return type need not be explicitly specified. The function might as well be declared as follows:

fun printSum(a: Int, b: Int): Unit {
  print(a + b)
}

Note

An identifier is not required for a function. Functions that do not possess an identifier are called anonymous functions. Anonymous functions are present in Kotlin in the form of lambdas.

Invoking functions

Functions are not executed once they are defined. In order for the code within a function to be executed, the function must be invoked. Functions can be invoked as functions, as methods, and indirectly by utilizing the invoke() and call() methods. The following shows the direct functional invocation using the function itself:

fun repeat(word: String, times: Int) { 
  var i = 0

  while (i < times) {
    println(word)
    i++
  }
}

fun main(args: Array<String>) {
  repeat("Hello!", 5)
}

Compile and run the preceding code. The word Hello is printed on the screen five times. Hello was passed as our first value in the function and 5 as our second.  As a result of this, the word and times arguments are set to hold the Hello and 5 values in our repeat function. Our while loop runs and prints our word as long as i is less than the number of times specified. i++ is used to increase the value of i by 1. i is increased by one upon each iteration of the loop. The loop stops once i is equal to 5. Hence, our word Hello will be printed five times. Compiling and running the program will give us the following output:

The other methods of function invocation will be demonstrated over the course of this book.

Return values

A return value—as the name implies—is the value that a method returns. Functions in Kotlin can return values upon execution. The type of the value returned by a function is defined by the function's return type. This is demonstrated in the following code snippet:

fun returnFullName(firstName: String, surname: String): String {
  return "${firstName} ${surname}"
}

fun main(args: Array<String>) {
val fullName: String = returnFullName("James", "Cameron")
println(fullName) // prints: James Cameron
}

In the preceding code, the returnFullName function takes two distinct strings as its input parameters and returns a string value when called. The return type has been defined in the function header. The string returned is created via string templates:

"${firstName} ${surname}"

The values for first name and last name are interpolated into the string of characters.

The function naming convention

The conventions for naming functions in Kotlin are similar to that of Java. When naming methods, camel case is utilized. In camel case, names are written such that each word in the name begins with a capital letter, with no intervening spaces or punctuation:

//Good function name
fun sayHello() {
println("Hello")
}

//Bad function name
fun say_hello() {
println("Hello")
}

Comments

When writing code, you may need to jot down important information pertaining to the code being written. This is done through the use of comments. There are three types of comments in Kotlin:

  • Single-line comments
  • Multiline comments
  • Doc comments
Single-line comments

As the name implies, these comments span a single line. Single-line comments are started with two backslashes (//). Upon compilation of your program, all characters coming after these slashes are ignored. Consider the following code:

val b: Int = 957 // This is a single line comment
// println(b)

The value held by b is never printed to the console because the function that performs the printing operation has been commented out.

Multiline comments

Multiline comments span multiple lines. They are started with a backslash followed by an asterisk (/*) and ended by an asterisk followed by a backslash (*/):

/*
 * I am a multiline comment.
 * Everything within me is commented out.
*/
Doc comments

This type of comment is similar to a multiline comment. The major difference is that it is used to document code within a program. A doc comment starts with a backslash followed by two asterisk characters (/**) and ends with an asterisk followed by a backslash (*/):

/**
* Adds an [item] to the queue.
* @return the new size of the queue.
*/
fun enqueue(item: Object): Int { ... }

Controlling program flow

When writing programs, a scenario that often occurs is one in which we want to control how our program executes. This is necessary if we want to write programs that can make decisions based on conditions and program state. Kotlin possesses a number of structures for doing this, which will be familiar to people who have worked with programming languages in the past, such as if, while, and for constructs. There are also others that may not be familiar to individuals, such as the when construct. In this section, we will take a look at the structures at our disposal for controlling the flow of our program.

Conditional expressions

Conditional expressions are used for branching program flow. They execute or skip program statements based on the outcome of a conditional test. Conditional statements are the decision-making points of a program.

Kotlin has two main structures for handling branching. These are if expressions and when expressions.

The if expression

The if expression is used to make a logical decision based on the fulfillment of a condition. We make use of the if keyword to write if expressions:

val a = 1

if (a == 1) {
print("a is one")
} 

The preceding if expression tests whether the a == 1 (read: a is equal to 1) condition holds true. If the condition is true, the a is one string is printed on the screen, otherwise nothing is printed.

An if expressions often has one or more accompanying else or else if keywords. These accompanying keywords can be used to further control the flow of a program. Take the following if expression for example:

val a = 4
if (a == 1) {
  print("a is equal to one.")
} else if (a == 2) {
print("a is equal to two.")
} else {
print("a is neither one nor two.")
}

The preceding expression first tests whether a is equal to 1. This test evaluates to false so, the following condition has been tested. Surely a is not equal to 2. Hence the second condition evaluates to false. As a result of all previous conditions evaluating to false, the final statement is executed. Hence a is neither one nor two. is printed on the screen.

The when expression

The when expression is another means of controlling program flow. Let's observe how it works with a simple example:

fun printEvenNumbers(numbers: Array<Int>) {
numbers.forEach {
when (it % 2) {
0 -> println(it)
}
}
}

fun main (args: Array<String>) {
val numberList: Array<Int> = arrayOf(1, 2, 3, 4, 5, 6)
printEvenNumbers(numberList)
}

The preceding printEvenSum function takes an integer array as its only argument. We will cover arrays later on in this chapter, but for now think of them as a sequential collection of values existing in a value space. In this case, the array passed contains values that exist in the value space of integers. Each element of the array is iterated upon using the forEach method and each number is tested in the when expression.

Here, the it refers to the current value being iterated upon by the forEach method. The % operator is a binary operator that acts on two operands. It divides the first operand by the second and returns the remainder of the division. Thus, the when expression tests if/when the current value iterated upon (the value held within it) is divided by 2 and has a remainder of 0. If it does, the value is even and hence the value is printed.

To observe how the program works, copy and paste the preceding code into a file, then compile and run the program:

The Elvis operator

The Elvis operator is a terse structure that is present in Kotlin. It takes the following form:

(expression) ?: value2

Its usage in a Kotlin program is demonstrated in the following code block:

val nullName: String? = null
val firstName = nullName ?: "John"

If the value held by nullName is not null, the Elvis operator returns it, otherwise the "John" string is returned. Thus, firstName is assigned the value returned by the Elvis operator.

Loops

Looping statements are used to ensure that a collection of statements within a block of code repeats in execution. That is, a loop ensures that a number of statements within a program executes for a number of times. The looping constructs provided by Kotlin are the for loop, the while loop, and the do…while loop.

The for loops

The for loop in Kotlin iterates over any object that provides an iterator. It is similar to the for..in loop in Ruby. The loop has this syntax:

for (obj in collection) { … }

The block in the for loop is not necessary if only a single statement exists in the loop. A collection is a type of structure that provides an iterator. Consider the following program:

val numSet = arrayOf(1, 563, 23)

for (number in numSet) {
println(number)
}

Each value in the numSetarray is iterated upon by the loop and assigned to the variable number. The number is then printed to the standard system output.

Note

Every element of an array has an index. An index is the position an element holds within an array. The set of indices of an array in Kotlin starts from zero.

If instead of printing the numeric values of the number iterated upon, we wish to print the indices of each number, we can do that as follows:

for (index in numSet.indices) {
println(index)
}

You can specify a type for your iterator variable as well:

for (number: Int in numSet) {
println(number)
}
The while loops

A while loop executes instructions within a block as long as a specified condition is met. The while loops are created using the while keyword. It takes the following form:

while (condition) { … }

As in the case of the for loop, the block is optional in the case where only one sentence is within the scope of the loop. In a while loop, the statements in the block execute repeatedly while the condition specified still holds. Consider the following code:

val names = arrayOf("Jeffrey", "William", "Golding", "Segun", "Bob")
var i = 0

while (!names[i].equals("Segun")) {
println("I am not Segun.")
i++
}

In the preceding program, the block of code within the while loop executes and prints I am not Segun until the name Segun is encountered. Once Segun is encountered, the loop terminates and nothing else is printed out, as shown in the following screenshot:

The break and continue keywords

Often when declaring loops, there is a need to either break out of the loop if a condition fulfills, or start the next iteration at any point in time within the loop. This can be done with the break and continue keywords. Let's take an example to explain this further. Open a new Kotlin script file and copy the following code into it:

data class Student(val name: String, val age: Int, val school: String)

val prospectiveStudents: ArrayList<Student> = ArrayList()
val admittedStudents: ArrayList<Student> = ArrayList()

prospectiveStudents.add(Student("Daniel Martinez", 12, "Hogwarts"))
prospectiveStudents.add(Student("Jane Systrom", 22, "Harvard"))
prospectiveStudents.add(Student("Matthew Johnson", 22, "University of Maryland"))
prospectiveStudents.add(Student("Jide Sowade", 18, "University of Ibadan"))
prospectiveStudents.add(Student("Tom Hanks", 25, "Howard University"))

for (student in prospectiveStudents) {
if (student.age < 16) {
continue
}
admittedStudents.add(student)

if (admittedStudents.size >= 3) {
break
}
}

println(admittedStudents)

The preceding program is simplistic software for selecting admitted students out of a list of prospective students. We create a data class at the start of our program to model the data of each student, then two array lists are created. One array list holds the information of the prospective students, those that have applied for admission, and the other list holds the information of the students that have been admitted.

The next five lines of code add prospective students to the prospective student list. We then declare a loop that iterates over all students present in the prospective student list. If the age of the current student in the loop is less than 16 years old, the loop skips to the next iteration. This models the scenario in where a student is too young to be admitted (thus not added to the admitted students list).

If the student is 16 or older, the student is added to the admitted list. An if expression is then used to check whether the number of admitted students is greater than or equal to three. If the condition is true, the program breaks out of the loop and no further iterations are done. The last line of the program prints out the students present in the list.

Run the program to see the output:

The do…while loops

The do…while loop is similar to the while loop, with the exception that in the conditional test for the reiteration of the loop, it is carried out after the first iteration. It takes the following form:

do { 
...
} while (condition) 

The statements within the block are executed while the condition tested holds true:

var i = 0

do {
println("I’m in here!")
i++
} while (i < 10)

println("I’m out here!")

Nullable values: The NullPointerException is one thing that individuals who have first-hand experience writing Java code are certain to have encountered. The Kotlin type system is null-safe—it attempts to eliminate the occurrence of null references within code. As a result, Kotlin possesses nullable types and non-nullable types (types that can hold a null value and those that can't).

To properly explain the NullPointerException, we will consider the following Java program:

class NullPointerExample {

public static void main(String[] args) {
String name = "James Gates";
System.out.println(name.length()); // Prints 11

name = null; // assigning a value of null to name
System.out.println(name.length()); // throws NullPointerException
}
}

The preceding program performs the simple task of printing the length of a string variable to the standard system output. There is only one problem with our program. When we compile and run it, it throws a null pointer exception and terminates midway through execution, as we can see the following screenshot:

Can you spot the cause of the NullPointerException? The exception arises as a result of the String#length method being used on a null reference. As such, the program stops executing and throws the exception. Clearly, this is not something we want to occur in our programs.

We can prevent this in Kotlin by preventing the assignment of a null value to the name object:

var name: String = "James Gates"
println(name.length)

name = null // null value assignment not permitted
println(name.length)

As can be seen in the following screenshot, Kotlin's type system detects that a null value has been inappropriately assigned to the name variable and swiftly alerts the programmer of this blunder so it can be corrected:

At this point, you may be wondering what happens if a scenario arises in which the programmer intends to permit the passing of null values. In that scenario, the programmer simply declares the value as nullable by appending ? to the type of the variable:

var name: String? = "James"
println(name.length)

name = null // null value assignment permitted
println(name.length)

Regardless of the fact that we have declared the variable name to be nullable, we'll still get an error upon running the program. This is because we must access the length property of the variable in a safe way. This can be done with ?.:

var name: String? = "James"
println(name?.length)

name = null // null value assignment permitted
println(name?.length)

Now that we have used the ?. safe operator, the program will run as intended. Instead of a null pointer exception being thrown, the type system recognizes that a null pointer has been referenced and prevents the invocation of length() on the null object. The following screenshot shows the type-safe output:

An alternative to using the ?. safe operator would be to use the !! operator. The !! operator allows the program to continue execution and throws a KotlinNullPointerException once a function invocation is attempted on a null reference.

We can see the effects by replacing ?. with !!. in our written program. The following screenshot shows the output of the program when run. A KotlinNullPointerException is thrown as a result of the utilization of the !! operator:

Packages

A package is a logical grouping of related classes, interfaces, enumerations, annotations, and functions. As source files grow larger, it is necessary to group these files into meaningful and distinct collections for various reasons, such as to enhance the maintainability of applications, name conflict prevention, and access control.

A package is created with the package keyword followed by a package name:

package foo

There can be only one package statement per program file. If a package for a program file is not specified, the contents of the file are placed into the default package.

The import keyword

Often, classes and types need to make use of other classes and types existing outside the package in which they are declared. This can be done by importing package resources. If two classes belong in the same package, no import is necessary:

package animals
data class Buffalo(val mass: Int, val maxSpeed: Int, var isDead: Boolean = false)

In the following code snippet, the Buffalo class does not need to be imported into the program because it exists in the same package (animals) as the Lion class:

package animals
class Lion(val mass: Int, val maxSpeed: Int) {

fun kill(animal: Buffalo) { // Buffalo type used with our import
if (!animal.isDead) {
println("Lion attacking animal.")
animal.isDead = true
println("Lion kill successful.")
}
}
}

In order to import classes, functions, interfaces, and types in separate packages, we use the import keyword followed by the package name. For example, the following main function exists in the default package. As such, if we want to make use of the Lion and Buffalo classes in the main function, we must import it with the import keyword. Consider the following code:

import animals.Buffalo
import animals.Lion

fun main(args: Array<String>) {
val lion = Lion(190, 80)
val buffalo = Buffalo(620, 60)
println("Buffalo is dead: ${buffalo.isDead}")
lion.kill(buffalo)
println("Buffalo is dead: ${buffalo.isDead}")
}

Object-oriented programming concepts

Up till now, we have made used of classes in a number of examples but have not explored the concept in depth. This section will introduce you to the basics of classes as well as other object-oriented constructs available in Kotlin. 

Introduction

In the beginning of high-level programming languages, programs were written procedurally. The programming languages available were mainly procedural in nature. A procedural programming language is a language that utilizes a series of structured, well-defined steps to compose programs.

As the software industry grew larger and programs grew bulkier, it became necessary to devise a better approach to designing software. This led to the advent of object-oriented programming languages.

The object-oriented programming model is a model organized around objects and data rather than actions and sequential logic. In object-oriented programming, objects, classes, and interfaces are composed, extended, and inherited toward the goal of building industrial-strength software.

A class is a modifiable and extensible program template for the creation of objects and the maintenance of state through the use of variables, constants, and properties. A class possesses characteristics and behaviors. Characteristics are exposed as variables and behaviors are implemented in the form of methods. Methods are functions that are specific to a class or a collection of classes. Classes have the ability to inherit characteristics and behaviors from other classes. This ability is called inheritance.

Kotlin is a fully object-oriented programming language and hence supports all features of object-oriented programming. In Kotlin, similar to Java and Ruby, only single inheritance is permitted. Some languages, such as C++, support multiple inheritance. A downside to multiple inheritance is that it brings up management issues, such as same name collisions. A class inheriting from another class is referred to as a subclass and the class it inherits from is its superclass.

An interface is a structure that enforces certain characteristics and behaviors in classes. Behavioral enforcements via interfaces can be done by implementing an interface in a class. Similar to classes, an interface can extend another interface.

An object is an instance of a class that may possesses its own unique state.

Working with classes

A class is declared using the class keyword followed by the class name:

class Person

As in the preceding example, a class in Kotlin need not have a body. Though this is charming, almost all the time you will want your class to have characteristics and behaviors placed within a body. This can be done with the use of opening and closing brackets:

class HelloPrinter {
  fun printHello() {
    println("Hello!")
  }
}

In the preceding code snippet, we have a class named HelloPrinter with a single function declared in it. A function that is declared within a class is called a method. Methods can also be referred to as behaviors. Once a method is declared, it can be used by all instances of the class.

Creating objects

Declaring an instance of a class—or an object—is similar to declaring a variable. We can create an instance of the HelloPrinter class, as shown in the following code:

val printer = HelloPrinter()

The preceding printer is an instance of the HelloPrinter class. The opening and closing brackets after the HelloPrinter class name are used to invoke the primary constructor of the HelloPrinter class. A constructor is similar to a function. A constructor is a special function that initializes an object of a type.

The function declared within the HelloPrinter class can be invoked directly by the printer object at any point in time:

printer.printHello() // Prints hello

Occasionally, you may require a function to be directly invokable with the class without needing to create an object. This can be done with the use of a companion object.

Companion objects

Companion objects are declared within a class by utilizing the companion and object keywords. You can use functions that are static within a companion object:

class Printer {
  companion object DocumentPrinter {
    fun printDocument() = println("Document printing successful.")
  }
}

fun main(args: Array<String>) {
  Printer.printDocument() // printDocument() invoked via companion object
  Printer.Companion.printDocument() // also invokes printDocument() via 
                                    // a companion object
}

Sometimes, you may want to give an identifier to a companion object. This can be done by placing the name after the object keyword. Consider the following example:

class Printer {
  companion object DocumentPrinter { // Companion object identified by DocumentPrinter
    fun printDocument() = println("Document printing successful.")
  }
}

fun main(args: Array<String>) {
  Printer.DocumentPrinter.printDocument() // printDocument() invoked via
                                          // a named companion object
}

Properties

Classes can have properties that may be declared using the var and val keywords. For example, in the following code snippet, the Person class has three properties, age, firstName, and surname:

class Person { var age = 0
var firstName = ""
var surname = ""
}

Properties can be accessed through an instance of the class holding the property. This is done by appending a single dot character (.) to an instance identifier followed by the property name. For example, in the following code snippet, an instance—named person—of the Person class is created and its firstName, surname, and age properties are assigned by accessing the properties:

val person = Person()
person.firstName = "Raven"
person.surname = "Spacey"
person.age = 35
 

Advantages of Kotlin


As previously discussed, Kotlin was designed to be a better Java, and as such, there are a number of advantages to using Kotlin over Java:

  • Null safety: One common occurrence in Java programs is the throwing of NullPointerException. Kotlin alleviates this issue by providing a null-safe type system.
  • Presence of extension functions: Functions can easily be added to classes defined in program files to extend their functionality in various ways. This can be done with extension functions in Kotlin.
  • Singletons: It is easy to implement the singleton pattern in Kotlin programs. The implementation of a singleton in Java takes considerably more effort than when it is done with Kotlin.
  • Data classes: When writing programs, it is a common scenario to have to create a class for the sole purpose of holding data in variables. This often leads to the writing of many lines of code for such a mundane task. Data classes in Kotlin make it extremely easy to create such classes that hold data with a single line of code.
  • Function types: Unlike Java, Kotlin has function types. This enables functions to accept other functions as parameters and the definition of functions that return functions.
 

Developing Android applications with Kotlin


We have taken a concise look at some of the features Kotlin has put at our disposal for developing powerful applications. Over the course of this book, we will explore how these features can be utilized in Android application development - an area in which Kotlin shines.

Before getting started on this journey, we must set up our systems for the task at hand. A major necessity for developing Android applications is a suitable IDE - it is not a requirement but it makes the development process easier. Many IDE choices exist for Android developers. The most popular are:

  • Android Studio
  • Eclipse
  • IntelliJ IDE

Android Studio is by far the most powerful of the IDEs available with respect to Android development. As a consequence, we will be utilizing this IDE in all Android-related chapters in this book.

Setting up Android Studio

At the time of writing, the version of Android Studio that comes bundled with full Kotlin support is Android Studio 3.0. The canary version of this software can be downloaded from https://developer.android.com/studio/preview/index.html. Once downloaded, open the downloaded package or executable and follow the installation instructions. A setup wizard exists to guide you through the IDE setup procedure:

Continuing to the next setup screen will prompt you to choose which type of Android Studio setup you'd like:

Select the Standard setup and continue to the next screen. Click Finish on the Verify Settings screen. Android Studio will now download the components required for your setup. You will need to wait a few minutes for the required components to download:

Click Finish once the component download has completed. You will be taken to the Android Studio landing screen. You are now ready to use Android Studio:

Building your first Android application

Without further ado, let's explore how to create a simple Android application with Android Studio. We will be building the HelloApp. The HelloApp is an app that displays Hello world! on the screen upon the click of a button.

On the Android Studio landing screen, click Start a new Android Studio project. You will be taken to a screen where you will specify some details that concern the app you are about to build, such as the name of the application, your company domain, and the location of the project.

Type in HelloApp as the application name and enter a company domain. If you do not have a company domain name, fill in any valid domain name in the company domain input box – as this is a trivial project, a legitimate domain name is not required. Specify the location in which you want to save this project and tick the checkbox for the inclusion of Kotlin support.

After filling in the required parameters, continue to the next screen:

Here, we are required to specify our target devices. We are building this application to run on smartphones specifically, hence tick the Phone and Tablet checkbox if it's not already ticked. You will notice an options menu next to each device option. This dropdown is used to specify the target API level for the project being created. An API level is an integer that uniquely identifies the framework API division offered by a version of the Android platform.  Select API level 15 if not already selected and continue to the next screen:

On the next screen, we are required to select an activity to add to our application. An activity is a single screen with a unique user interface—similar to a window. We will discuss activities in more depth in Chapter 2, Building an Android Application – Tetris. For now, select the empty activity and continue to the next screen.

Now, we need to configure the activity that we just specified should be created. Name the activity HelloActivity and ensure the Generate Layout File and Backwards Compatibility checkboxes are ticked:

Now, click the Finish button. Android Studio may take a few minutes to set up your project. Once the setup is complete, you will be greeted by the IDE window containing your project files.

Note

Errors pertaining to the absence of required project components may be encountered at any point during project development. Missing components can be downloaded from the SDK manager.

Make sure that the project window of the IDE is open (on the navigation bar, select View | Tool Windows | Project) and the Android view is currently selected from the drop-down list at the top of the Project window. You will see the following files at the left-hand side of the window:

  • app | java | com.mydomain.helloapp | HelloActivity.java: This is the main activity of your application. An instance of this activity is launched by the system when you build and run your application:
  • app | res | layout | activity_hello.xml: The user interface for HelloActivity is defined within this XML file. It contains a TextView element placed within the ViewGroup of a ConstraintLayout. The text of the TextView has been set to Hello World!
  • app | manifests | AndroidManifest.xml: The AndroidManifest file is used to describe the fundamental characteristics of your application. In addition, this is the file in which your application's components are defined.
  • Gradle Scripts | build.gradle: Two build.gradle files will be present in your project. The first build.gradle file is for the project and the second is for the app module. You will most frequently work with the module's build.gradle file for the configuration of the compilation procedure of Gradle tools and the building of your app.

Note

Gradle is an open source build automation system used for the declaration of project configurations. In Android, Gradle is utilized as a build tool with the goal of building packages and managing application dependencies.

Creating a user interface

A user interface (UI) is the primary means by which a user interacts with an application. The user interfaces of Android applications are made by the creation and manipulation of layout files. Layout files are XML files that exist in app | res | layout.

To create the layout for the HelloApp, we are going to do three things:

  1. Add a LinearLayout to our layout file
  2. Place the TextView within the LinearLayout and remove the android:text attribute it possesses
  3. Add a button to the LinearLayout

Open the activity_hello.xml file if it's not already opened. You will be presented with the layout editor. If the editor is in the Design view, change it to its Text view by toggling the option at the bottom of the layout editor. Now, your layout editor should look similar to that of the following screenshot:

A LinearLayout is a ViewGroup that arranges child views in either a horizontal or vertical manner within a single column. Copy the code snippet of our required LinearLayout from the following block and paste it within the ConstraintLayout preceding the TextView:

<LinearLayout
android:id="@+id/ll_component_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
</LinearLayout>

Now, copy and paste the TextView present in the activity_hello.xml file into the body of the LinearLayout element and remove the android:text attribute:

<LinearLayout
android:id="@+id/ll_component_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
<TextView
android:id="@+id/tv_greeting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
       android:textSize="50sp" />
</LinearLayout>

Lastly, we need to add a button element to our layout file. This element will be a child of our LinearLayout. To create a button, we use the Button element:

<LinearLayout
 android:id="@+id/ll_component_container"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
 android:gravity="center">
<TextView
 android:id="@+id/tv_greeting"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
       android:textSize="50sp" />
<Button
       android:id="@+id/btn_click_me"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_marginTop="16dp"
 android:text="Click me!"/>
</LinearLayout>

Toggle to the layout editor's design view to see how the changes we have made thus far translate when rendered on the user interface:

Now we have our layout, but there's a problem. Our CLICK ME! button does not actually do anything when clicked. We are going to fix that by adding a listener for click events to the button. Locate and open the HelloActivity.java file and edit the function to add the logic for the CLICK ME! button's click event as well as the required package imports, as shown in the following code:

package com.mydomain.helloapp
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.widget.Button
import android.widget.TextView
import android.widget.Toast

class HelloActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_hello)
val tvGreeting = findViewById<TextView>(R.id.tv_greeting)
val btnClickMe = findViewById<Button>(R.id.btn_click_me)

btnClickMe.setOnClickListener {
if (TextUtils.isEmpty(tvGreeting.text)) {
tvGreeting.text = "Hello World!"
} else {
Toast.makeText(this, "I have been clicked!", 
                       Toast.LENGTH_LONG).show()
}
}
}
}

In the preceding code snippet, we have added references to the TextView and Button elements present in our activity_hello layout file by utilizing the findViewById function. The findViewById function can be used to get references to layout elements that are within the currently-set content view. The second line of the onCreate function has set the content view of HelloActivity to the activity_hello.xml layout.

Next to the findViewById function identifier, we have the TextView type written between two angular brackets. This is called a function generic. It is being used to enforce that the resource ID being passed to the findViewById belongs to a TextView element.

After adding our reference objects, we set an onClickListener to btnClickMe. Listeners are used to listen for the occurrence of events within an application. In order to perform an action upon the click of an element, we pass a lambda containing the action to be performed to the element's setOnClickListener method. 

When btnClickMe is clicked, tvGreeting is checked to see whether it has been set to contain any text. If no text has been set to the TextView, then its text is set to Hello World!, otherwise a toast is displayed with the I have been clicked! text.

Running the application

In order to run the application, click the Run 'app' (^R) button at the top-right side of the IDE window and select a deployment target. The HelloApp will be built, installed, and launched on the deployment target:

You may use one of the available prepackaged virtual devices or create a custom virtual device to use as the deployment target.  You may also decide to connect a physical Android device to your computer via USB and select it as your target. The choice is up to you. After selecting a deployment device, click OK to build and run the application. 

Upon launching the application, our created layout is rendered:

 

When CLICK ME! is clicked, Hello World! is shown to the user:

Subsequent clicks of the CLICK ME! button display a toast message with the text I have been clicked!:

 

Fundamentals of the web


Most applications communicate with a server in one way or another. It is imperative that you understand a number of concepts related to the web before continuing in this book. This section explains those concepts concisely.

What is the web?

The web is a complex system of interconnected systems possessing the ability to communicate with other systems existing on a common network via one or more protocols. A protocol is an official, well-defined system of rules governing the exchange of information between devices.

Hypertext Transfer Protocol

All communications over the web are made in accordance with a protocol. A particularly important protocol for fostering communication between systems is the Hypertext Transfer Protocol (HTTP).

Billions of images, videos, text files, documents, and other files are transferred across the internet on a daily basis. These files are all transferred through HTTP. HTTP is an application protocol for distributed and hypermedia information systems. It can be said to be a foundational component for communication across the internet. A major benefit of using HTTP for data transfer across systems is that it is highly reliable. This is as a result of its utilization of reliable protocols, such as the Transmission Control Protocol (TCP) and Internet Protocol (IP).

Clients and servers

A web client is any application that communicates with a web server utilizing HTTP. A web server is a computer that provides – or serves – web resources to web clients. A web resource is anything that provides web content. A web resource can be a media file, an HTML document, a gateway, and so on. Clients need web content for various purposes, such as information rendering and data manipulation.

Clients and servers communicate with each other via HTTP. One major reason for the utilization of HTTP is the fact that it is extremely reliable in data transmission. The use of HTTP ensures data loss does not occur in a request-response cycle.

HTTP requests and responses

An HTTP request – as the name replies – is a solicitation for a web resource sent by a web client to a server over HTTP. An HTTP response is a reply – sent by a server – to a request in an HTTP transaction:

HTTP methods

HTTP supports a number of request methods. These methods can also be referred to as commands. HTTP methods specify the type of action to be performed by the server. Some common HTTP methods are tabularized as follows:

HTTP method

Description

GET

Retrieves a named resource present on the client.

POST

Sends data from a client to a server.

DELETE

Deletes a named resource residing on a server.

PUT

Store data collected by the client in a named resource residing on the server.

OPTIONS

Returns HTTP methods that the server supports.

HEAD

Retrieves HTTP headers with no content.

 

Summary


In this chapter, we were introduced to Kotlin and explored its fundamentals. In the process, we learned how to install Kotlin on a computer, what an IDE is, the IDEs at your disposal for writing programs in Kotlin, how to write and run Kotlin scripts, and how to use the REPL. In addition, we learned how to work with both IntelliJ IDEA and Android Studio, after which we implemented a simple Android application. Lastly, we had a look at the fundamental concepts related to the web. 

In the next chapter, we will get more familiar with writing Kotlin programs by creating an Android application. We will take a look at the Android application architecture and the important components of an Android application, as well as many more topics.

 

About the Author

  • Iyanu Adelekan

    Iyanu Adelekan is a software engineer who enjoys solving problems in the web and Android application domains. He loves working on open source projects and is the author and lead maintainer of Kanary, a Kotlin web framework for building RESTful application programming interfaces. In addition to building software, he is passionate about knowledge sharing and algorithms. He enjoys reading sci-fi and playing chess in his spare time.

    Browse publications by this author

Latest Reviews

(4 reviews total)
Great content and I like the PDF format choice.
Lecture très agréable, explication concises et claires
it has what i wanted. This book demands some experience in programming

Recommended For You

Learn Kotlin Programming - Second Edition

Delve into the world of Kotlin and learn to build powerful Android and web applications

By Stephen Samuel and 1 more
Mastering Kotlin

Explore popular language features, Java to Kotlin interoperability, advanced topics, and practical applications by building a variety of sample projects

By Nate Ebel
Android Programming with Kotlin for Beginners

Build smart looking Kotlin apps with UI and functionality for the Android platform

By John Horton
Hands-on Design Patterns with Kotlin

Make the most of Kotlin by leveraging design patterns and best practices to build scalable and high performing apps

By Alexey Soshin