Android: Kotlin Tutorial – Basic Syntax

I am also a beginner in Kotlin, if there is any mistake, please help to point out, continue to update

  • Kotlin is officially recognized by Google as a level 1 programming language for Android development
  • Since Google I/O in 2019, Kotlin has been the go-to choice for Android mobile development.
  • Let’s start with Kotlin’s basic syntax

What is Kotlin

  • Kotlin is a level 1 programming language developed for Android (official Google certification)
  • Launched in 2010 by JetBrains & open source, interworking with the Java language & with a number of new features not yet supported by Java
  • Versions of Android Studio3.0 and later support Kotlin

advantages

  • Less code, more readability – spend less time writing code and understanding other people’s code
  • Mature Languages and Environments – Since its inception in 2011, Kotlin has evolved not only through languages but also through powerful tools throughout the ecosystem. It is now seamlessly integrated into Android Studio and is being actively used by many companies to develop Android applications.
  • Kotlin support in Android Jetpack and other libraries – The KTX extension adds Kotlin language features such as coroutines, extension functions, lambdas, and named parameters to existing Android libraries.
  • Interoperability with Java – Kotlin can be used with the Java programming language in applications without having to migrate all code to Kotlin.
  • Support for multi-platform development – Kotlin can be used to develop not only Android, but also iOS, back-end and Web applications. Enjoy the benefits of sharing common code across platforms.
  • Code security – Less code with better readability leads to fewer errors. The Kotlin compiler detects these remaining errors to make the code safe.
  • Easy to learn and Use – Kotlin is very easy to learn, especially for Java developers.
  • Large Community – Kotlin receives strong support and many contributions from the community, which is growing worldwide. According to Google, more than 60% of the top 1,000 apps on the Play Store use Kotlin.

use

Click on Android Studio Settings -> Plugins -> search for Kotlin Languages Plugins

buildscript {
    ext.kotlin_version = '1.3.61'
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"}}Copy the code

3. Add it in app/build.gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

buildscript {
    ext.kotlin_version = '1.3.61'
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"}}Copy the code

The basic grammar

Define the package name – Define the package name at the beginning of the source file: the package name does not have to be the same as the folder path: the source file can be placed anywhere.

package my.demo 
import java.util.
* / /...
Copy the code

Define a function: Define a function that takes two ints and returns an int

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

fun main(args: Array<String>) {
 	print("sum of 3 and 5 is ")
  	println(sum(3.5))}Copy the code

This function has a single expression body and a self-derived return value:

fun sum(a: Int, b: Int) = a + b 
fun main(args: Array<String>) {
 	println("sum of 19 and 23 is ${sum(19.23)}")}Copy the code

Returns a meaningless value: The return type of Unit can be omitted

fun printSum(a: Int, b: Int): Unit { 
	println("sum of $a and $b is ${a + b}")}fun main(args: Array<String>) { 
printSum(-1.8)}Copy the code

Define local variables to declare constants:

fun main(args: Array<String>) {
	 val a: Int = 1 // Initialize immediately
	 val b = 2 // Derive the Int
	 val c: Int // The type must be declared when no value is initialized
	 c = 3 / / assignment
	 println("a = $a, b = $b, c = $c")}Copy the code

Variables:

fun main(args: Array<String>) {
	 var x = 5 // Derive the Int type
	 x += 1 println("x = $x")}Copy the code

Comments: Like Java and javaScript, Kotlin supports single-line and block comments.

// Single-line comment
/* this is a block comment */
Copy the code

Unlike Java, Kotlin’s block annotations can be cascaded. Using string templates

fun main(args: Array<String>) {
	 var a = 1 // Use variable names as templates:
	 val s1 = "a is $a" a = 2 // Use an expression as a template:
	 val s2 = "${s1.replace("is"."was")}, but now is $a" println(s2)
 }
Copy the code

Using conditional expressions

fun maxOf(a: Int, b: Int): Int { 
	if (a > b) {
	 return a 
	 } else { 
	 return b
	  } 
 }
 fun main(args: Array<String>) { 
 	println("max of 0 and 42 is ${maxOf(0.42)}")}Copy the code

Use if as an expression:

fun maxOf(a: Int, b: Int) = if (a > b) a else b
fun main(args: Array<String>) {
	println("max of 0 and 42 is ${maxOf(0.42)}")}Copy the code

Using nullable variables and nullable checking should explicitly indicate that the reference is nullable when nullable values are possible. The following function returns null if STR contains no integers:

fun parseInt(str : String): Int? {/ /... }
Copy the code

Use value checking and automatic conversion Use the IS operator to check whether an expression is an instance of a type. If an immutable local variable or attribute is type-checked, there is no need to explicitly cast it:

fun getStringLength(obj: Any): Int? {
 if (obj is String) { 
 // obj will be automatically converted to String in this branch. Return obj.length}
 // obj still returns null outside the type check
 }
Copy the code

Using a loop

fun main(args: Array<String>) {
	 val items = listOf("apple"."banana"."kiwi") 
	 for (item in items) {
	  println(item) 
	  }
}
Copy the code

Or this:

fun main(args: Array<String>) { 
	val items = listOf("apple"."banana"."kiwi") 
	for (index in items.indices) {
	 println("item at $index is ${items[index]}")}}Copy the code

Use a while loop

fun main(args: Array<String>) { 
	 val items = listOf("apple"."banana"."kiwi")
	 var index = 0 while (index < items.size) { 
	 println("item at $index is ${items[index]}")
	  index++
	  }
}
Copy the code

Use when expressions

fun describe(obj: Any): String = 
	when (obj) {
	 1 -> "One" 
	 "Hello" ->"Greeting" 
	  is Long -> "Long" 
	  !is String -> "Not a string" 
	  else -> "Unknown" 
  }
  fun main(args: Array<String>) {
	     println(describe(1)) println(describe("Hello"))
	     println(describe(1000L))
	     println(describe(2)) 
	     println(describe("other"))}Copy the code

Use the ranges operator to check if the value is in a certain range:

fun main(args: Array<String>) { 
	val x = 10 
	val y = 9
	 if (x in 1..y+1) {
	  println("fits in range")}}Copy the code

Check if the value is outside the range:

if (-1 !in 0..list.lastIndex) { 
	println("-1 is out of range")}Copy the code

Using step by step

for (x in 1.10. step 2)
for (x in 9 downTo 0 step 3)
Copy the code

Using the collection

Iterate over a collection

fun main(args: Array<String>) { 
	val items = listOf("apple"."banana"."kiwi") 
	for (item in items) {
	 println(item) 
	 } 
 }
Copy the code

Use the IN operator to check if the collection contains an object

fun main(args: Array<String>) { 
	val items = setOf("apple"."banana"."kiwi") 
	when { 
	"orange" in items -> println("juicy") 
	"apple" in items -> println("apple is fine too")}}Copy the code

Use lambda expressions to filter and map collections

fun main(args: Array<String>) { 
	val fruits = listOf("banana"."avocado"."apple"."kiwi") 
	fruits 
	.filter { it.startsWith("a") } 
	.sortedBy { it } 
	.map { it.toUpperCase() } 
	.forEach { println(it) 
} 
Copy the code

idioms

Create DTOs(POJOs/POCOs) data classes that are equivalent to Java beans,

data class Customer(val name: String, val email: String)
Copy the code

Give the Customer class the following method — add getters for all attributes, and if you add setters — equals() — haseCode() — toString() — copy() for var types

Function defaults

fun foo(a: Int = 0, b: String = ""){... }Copy the code

Filter the list

val positives = list.filter { x -> x >0 }
Copy the code

Or even shorter:

val positives = list.filter { it > 0 }
Copy the code

String interpolation

println("Name $name")
Copy the code

Instance check

when (x) { 
	is Foo -> ... 
	is Bar -> ... 
	else -> ... 
}
Copy the code

Traverse map/list

for ((k, v) in map) {
	 print("$k -> $v")}Copy the code

K,v, you can call it whatever you want and you can use ranges

for (i in 1.100.) {... }// Closed interval: includes 100
for (i in 1 until 100) {... }// Half-open interval: not including 100
for (x in 2.10. step 2) {... }for (x in 10 downTo 1) {... }if (x in 1.10.) {... }for (i in 1.100.) {... }for (i in 2.10.) {... }Copy the code

A read-only list

val list = listOf("a"."b"."c")
Copy the code

Read the map

val map = mapOf("a" to 1."b" to 2."c" to 3)
Copy the code

Access to the map

println(map["key"]) 
map["key"] = value
Copy the code

Lazy properties (lazy loading)

val p: String by lazy { // Generate string value}
Copy the code

Extension function

fun String.spcaceToCamelCase(a){... }"Convert this to camelcase".spcaceToCamelCase()
Copy the code

Create a singleton pattern

object Resource {
 	val name = "Name"
}
Copy the code

If not empty… The shorthand

val files = File("Test").listFiles() println(files? .size)Copy the code

If not empty… Otherwise… The shorthand

val files = File("test").listFiles() println(files? .size ? :"empty")
Copy the code

Perform an operation if the declaration is null

val data=...val email = data["email"] ?: throw IllegalStateException("Email is missing!")
Copy the code

If the operation is not null, perform the operation

val date = ... 
data? .let{ ...// Execute the block if it is not null}
Copy the code

Return when judgment

fun transform(color: String): Int {
	 return when(color) { 
	 "Red" -> 0 "Green" -> 1 
	 "Blue" -> 2 
	 else -> throw IllegalArgumentException("Invalid color pa ram value")}}Copy the code

Try-catch expression

fun test(a) {
	 val result = try {
	  count() 
	  }catch (e: ArithmeticException) {
	   throw IllegaStateException(e)
	  }/ / processing result
}
Copy the code

If expression

fun foo(param: Int){ 
	val result = if (param == 1) { 
	"one"
	 } else if (param == 2) { 
	 "two" 
	 } else {
	  "three"}}Copy the code

A convenient form of a generic function that requires generic information

// public final class Gson { 
// ... 
// public <T> T fromJson(JsonElement json, Class<T> classOfT ) throws JsonSyntaxException { 
// ... inline 
fun <reified T: Any> Gson.fromJson(json): T = this.fromJs on(json, T::class.java)
Copy the code

Naming style

If in doubt, default to Java coding conventions, such as using Locke

  • Camel nomenclature (avoid underscores in naming)
  • The first letter of the type name is uppercase
  • Methods and properties begin with lowercase letters
  • Indent with four Spaces
  • The public method is documented so that it can appear in the Kotllin Doc

The colon

There should be Spaces between colons and parent types. There is no space between instances and types:

interface Foo<out T : Any> : Bar {
	fun foo(a: Int): T
}
Copy the code

Lambdas

In Lambdas, Spaces are required between braces and expressions, and between arrows and arguments and function bodies. Pass lambda outside parentheses as much as possible

list.filter { it > 10 }.map { element -> element * 2 }
Copy the code

In lambdas that use briefness rather than nesting, it is recommended to declare parameters using IT rather than explicitly. In nested lambdas that use arguments, arguments should always be explicitly declared

Class declaration format

Classes with fewer arguments can be represented by a line:

class Person(id: Int, name: String)
Copy the code

Classes with more arguments should be formatted so that each constructor argument is indented on a separate line. Also, the closing parenthesis should be on the new line. If we use inheritance, the list of interfaces that the superclass constructor calls or implements should be on the same line as the parentheses

class Person( 
	id: Int, 
	name: String, 
	surname: String 
	) : Human(id, name) {
	 // ... 
}
Copy the code

For multiple interfaces, the superclass constructor call should be located first, and then each interface should be located on a different line

class Person( 
	id: Int, 
	name: String, 
	surname: String 
	) : Human(id, name), 
	KotlinMaker { // ... 
}
Copy the code

Constructor arguments can be indent normally or continuously (double normal indentation).

Unit

If the function returns Unit, the return type should be omitted:

fun foo(a) { // ": Unit" is omitted}
Copy the code

Functions vs attributes

In some cases, functions with no arguments can be interchangeable with read-only attributes. Although the semantics are similar, there are stylistic conventions that favor one over the other when. Attributes rather than functions are preferred in the following cases:

  • There is no need to throw an exception — it has O(1) complexity — a low-consumption calculation (or the result of the first run is cached) — returns the same result as the call

I am also a beginner in Kotlin, if there is any mistake, please help to point out, continue to update