Skip to content

2. Getting Started with Android Development

1 Introduction to Kotlin

  • Kotlin is a statically typed, cross-platform, general-purpose programming language with type inference.
  • To run a simple Kotlin script:
    1. Install kotlin and kotlinc (kotlin compiler).
    2. Create a file with .kt extension.
    3. Compile the file using kotlinc <filename>.kt.
    4. Run the compiled file using kotlin <filename>.

Data Types

  • Byte: 8-bit signed integer.
  • Integers:
    • Short: 16-bit signed integer.
    • Int: 32-bit signed integer.
    • Long: 64-bit signed integer.
  • Floats:
    • Float: 32-bit floating point number.
    • Double: 64-bit floating point number.
  • Boolean: true or false (1 bit).
  • Char: 16-bit Unicode character.
  • To Check if a variable is of a certain type, use is operator. .e.g. if (true is Boolean) { ... } or if (1 is Int) { ... }.

Variables

  • variables can be declared using var or val keywords.
  • val: Immutable variable, cannot be reassigned, but can be initialized with a variable or expression.
  • var: Mutable variable, local by default.
    var a: Int = 1
    val b = a + 1
    a++;

    println("a is ${a}"); // a is 2
    println("b is ${b}"); // b is 2

    b = 3; // Error: val cannot be reassigned
  • Ternary operator assignment:
    val max = if (a > b) { a } else { b }

When Expression

  • Similar to switch in C/C++.
var n = readLine()!!.toInt()
when (n) {
    1 -> println("1")
    2 -> println("2")
    3 -> println("3")
    4,5,6 -> println("4, 5 or 6")
    in 7..10 -> println("7, 8, 9 or 10")
    else -> {
        println("Invalid selection")
    }
}
  • You can also branch on type of a variable:
var x: Any = 1
when (x) {
    is Int -> print(x + 1)
    is String -> print(x.length + 1)
    is IntArray -> print(x.sum())
    else -> print("Unknown Type")
}
  • You can even branch on function calls:
fun isOdd(x: Int) = x % 2 != 0
fun isEven(x: Int) = x % 2 == 0

when {
    isOdd(x) -> print("x is odd")
    isEven(x) -> print("x is even")
    else -> print("x is funny")
}
  • You can use the result of a when in an assignment using a function:
fun transform(color: String): Int {
    return when (color) {
        "Red" -> 0
        "Green" -> 1
        "Blue" -> 2
        else -> throw IllegalArgumentException("Invalid color param value")
    }
}

or simpler:

fun transform(color: String): Int = when (color) {
    "Red" -> 0
    "Green" -> 1
    "Blue" -> 2
    else -> throw IllegalArgumentException("Invalid color param value")
}

For Loops

for (item in collection) {} // iterate over collection
for (i in 1..10) {} // range
for (i in 1..10 step 2) {} // range with step
for (i in 10..1){} // never executes as right bound is less than left bound
for (i in 10 downTo 1) {} // range in reverse
for (i in 10 downTo 1 step 2) {} // range in reverse with step

// for arrays
var arr = arrayOf(1, 2, 3, 4, 5);
for (i in arr.indices) {} // iterate over indices
for ((index, value) in arr.withIndex()) {} // iterate over indices and values

// strings
var str = "Hello World";
for (c in str) {} // iterate over characters
for ((index, value) in str.withIndex()) {} // iterate over indices and characters
for (i in str.indices) {} // iterate over indices

Functions

  • Functions can be declared using fun keyword.
  • Advantages: Reusability, modularity, readability, maintainability.
  • Disadvantages: Overhead, complexity.
  • Arguments can have default values to make them optional.
  • When calling a function, you can pass the name of the argument to make the code more readable; and you can also pass arguments in any order.
fun sum(a: Int, b: Int): Int {
    return a + b
}

fun sum(a: Int, b: Int = 0, c: Int = 0): Int {
    return a + b + c
}

fun main() {
    println(sum(1, 2)) // 3
    println(sum(1, b = 2)) // 3
    println(sum(1, c = 2)) // 3
    println(sum(1, c = 2, b = 3)) // 6
}
  • lambda functions are declared as val lambda_name : Data_type = { argument_List -> code_body }
val lambdaSum = { a: Int, b: Int -> a + b }
lambdaSum(1, 2) // 3
lambdaSum.invoke(1, 2) // 3

// Or, with explicit type declaration
val lambdaSum: (Int, Int) -> Int = { a, b -> a + b }

// Filter an array
val arr = arrayOf(1, 2, 3, 4, 5)
arr.filter { it % 2 == 0 } // [2, 4] // shorthand for arr.filter { x -> x % 2 == 0 }
arr.filter { it -> it % 2 == 0 } // [2, 4] // longhand
  • Anonymous functions are declared as val lambda_name = fun(argument_List): Data_type { code_body }
val mul = fun(a: Int, b: Int): Int { return a * b }
  • The inline keyword which ultimately requests the compiler to not allocate memory and simply copy the inlined code of that function at the calling place.
  • The infix keyword which allows you to call a function without using the dot and the parentheses. infix fun functionName(argument_List): Data_type { code_body } then you can call it as objectName functionName argument_List
  • Higher order functions are functions that take other functions as arguments or return functions.

Collections

  • Types of collections:
    1. List:
      • Ordered collection of elements that allows duplicates.
      • Immutable: val l = listOf(1,2,3) or val l = listOf<Int>(1,2,3), you can not add or remove elements from this list.
      • Mutable: can be created using functions like: mutableListOf, arrayListOF, and ArrayList.
    2. Set:
      • Unordered collection of elements that does not allow duplicates.
      • Immutable: val s = setOf(1,2,3) or val s = setOf<Int>(1,2,3), you can not add or remove elements from this set.
      • Mutable: can be created using functions like: mutableSetOf, hashSetOf, and HashSet.
    3. Map:
      • Collection of k**ey-value pairs** that does not allow duplicate keys.
      • Immutable: val m = mapOf(1 to "one", 2 to "two", 3 to "three") or val m = mapOf<Int, String>(1 to "one", 2 to "two", 3 to "three"), you can not add or remove elements from this map.
      • Mutable: can be created using functions like: mutableMapOf, hashMapOf, and HashMap.
    4. Array: Fixed size collection of elements that allows duplicates.
    5. Sequence: Lazy collection of elements that allows duplicates and can be processed only once.
  • Advantages of Collections: Readability, Performance, Better memory management, Type safety, and Storage Efficiency (over manual memory or file-based storage).
  • Disadvantages: Overhead, Complexity.
  • ArrayList: creates mutable list of elements by val al = ArrayList<Int>() or val al = arrayListOf<Int>(). Advantages: dynamic resizing, store different types, easy to use with useful methods. Disadvantages: more overhead, more memory usage, access time is slower.
var al = ArrayList<Int>() // constructor
al.add(1)
al.add(1, 2) // add element `2` at index 1, shifting all elements after index 1 to the right
al.addAll(2, listOf(3, 4, 5)) // add elements `3`, `4`, and `5` at index 2
al.get(1) // get element at index 1
al.remove(1) // remove element at index 1
al.set(1, 2) // set element at index 1 to `2`, replacing the previous element at index 1
al.indexOf(2) // get index of element `2`
al.size // get size of array
al.clear() // clear array
  • List: creates immutable collection of elements using val l = listOf<Int>(), can be accessed using indices rather than functions as l[0]. Advantages: Immutability, Type safety, Convenience (to store collection of fixed size that is not changing). Disadvantages: Immutability, overhead, limited functionality.
var l = listOf<Int>(1,2,3)
l.get(1) // get element at index 1
l[1] // get element at index 1
l.first() // get first element
l.last() // get last element
for (i in l) {} // iterate over elements
var it = l.listIterator() // get iterator
while (it.hasNext()) { } // iterate over elements using iterator
for (i in 0 until l.size) {} // iterate over elements using indices
l.sorted() // gives sorted list in ascending order
l.sortedDescending() // gives sorted list in descending order
l.contains(1) // check if list contains element `1`
l.containsAll(listOf(1,2)) // check if list contains all elements in the list
  • Set: creates immutable collection of elements using val s = setOf<Int>().
var s = setOf<Int>(1,2,3)
s.elementAt(1) // get element at index 1
s.indexOf(2) // get index of element `2`
s.lastIndexOf(2) // get last index of element `2`
s.first() // get first element
s.last() // get last element
s.count() // get number of elements
s.max() // get maximum element
s.min() // get minimum element
s.sum() // get sum of elements
s.average() // get average of elements
s.contains(1) // check if set contains element `1`
s.containsAll(listOf(1,2)) // check if set contains all elements in the list
s.isEmpty() // check if set is empty, empty sets are equal to each other `setOf<Int>() == setOf<Int>()`

2 Introduction to Android Development

  • Features of Android:
    • Open Source
    • Wide range of connectivity options: GSM, CDMA, Bluetooth, Wi-Fi, LTE, NFC, etc.
    • Rich API support: Camera, Bluetooth, Wi-Fi, Location, etc.
    • Rich Storage Management: SQLite, SharedPreferences, File System, etc.
    • Rich Media Support: Audio, Video, Images, etc.
    • Integrated WebView: WebKit engine for Hybrid apps.
    • Supports MultiTasking.
    • Supports AR/VR.
    • Rich Development Environment: Android Studio, Eclipse, IntelliJ IDEA, etc.
  • Latest Android Version is Android 13 (API level 33) and called Tiramisu.
  • Google made kotlin the official language for android development in 2017.

3 Meet Android Studio

  • Project Structure:
    • The Project structure represent the file on disk, while the Android structure represent the logical structure of the app folder.
    • Source Module Types: Android App modules, Library modules, and Google App Engine modules.
    • All build files are stored in the Gradle Scripts folder.
    • Each App has three folders:
      • manifests: contains the AndroidManifest.xml file that describes the structure of the app.
      • java: contains the java/kotlin code of the app.
      • res: contains the resources of the app.

4 Why Kotlin?

  • Apps like: Uber, Evernote, Pinterest moved to Kotlin.
  • It was selected as the preferred language for Android development by Google in 2017.
  • Kotlin has server-side, data science, Android, front-end, and cross-platform capabilities.
  • Kotlin is completely compatible with Java, but it has simpler syntax and easy to use features.
  • Kotlin reduces the code by 40% compared to Java.
  • Kotlin solves the null pointer exception problem by introducing nullable and non-nullable types.
  • Kotlin compiles into Intermediary Byte Code, which can be converted to any machine code.

References


  1. Adityamshidlyali. (2021, July 7). A complete guide to learn kotlin for android app development. GeeksforGeeks. Retrieved June 15, 2022, from https://www.geeksforgeeks.org/a-complete-guide-to-learn-kotlin-for-android-app-development/ 

  2. GeeksForGeeks (n.d.). Introduction to Android Development. https://www.geeksforgeeks.org/introduction-to-android-development/ 

  3. Android. (n.d.). Meet Android Studio. https://developer.android.com/studio/intro 

  4. AndroidDeveloper. (n.d.). Why Kotlin is More Populaer Than Java in Android Development. https://www.androiddeveloper.co.in/blog/why-kotlin-popular-than-java-android-development/#:~:text=Kotlin%20has%20100%25%20interoperability%20with,they%20call%20'better%20Java