============== Kotlin Android ============== .. toctree:: :maxdepth: 1 .. contents:: Librerie :local: :depth: 1 .. _introduction-kotlin-android: Introduzione ============ Kotlin è un linguaggio moderno perfetto per lo sviluppo di applicazioni Android che non introduce alcuna restrizione Alcune caratteristiche dell'uso di Kotlin per lo sviluppo delle app Android: - **Compatibilità**: Kotlin è completamente compatibile con JDK 6, garantendo che le applicazioni Kotlin possano funzionare su dispositivi Android precedenti senza problemi. Gli strumenti di Kotlin sono pienamente supportati in Android Studio e compatibili con il sistema di build Android. - **Prestazioni**: un'applicazione Kotlin è veloce quanto una Java equivalente, grazie a una struttura bytecode molto simile. Con il supporto di Kotlin per le funzioni inline, il codice che utilizza lambda spesso viene eseguito anche più velocemente dello stesso codice scritto in Java. - **Interoperabilità**: Kotlin è al 100% interoperabile con Java, consentendo di utilizzare tutte le librerie Android esistenti in un'applicazione Kotlin. Ciò include l'elaborazione delle annotazioni, quindi anche il databinding e il Dagger funzionano. - **Impatto**: Kotlin ha una libreria runtime molto compatta, che può essere ulteriormente ridotta con l'uso di ProGuard. In un'applicazione reale, il runtime di Kotlin aggiunge solo poche centinaia di metodi e meno di 100K alla dimensione del file .apk. - **Tempo di compilazione**: Kotlin supporta ed è ottimizzato per la compilazione incrementale, quindi, per le build pulite c'è un sovraccarico, le build incrementali sono solitamente veloci o più veloci rispetto a Java. - **Curva di apprendimento**: per uno sviluppatore Java, iniziare a usare Kotlin è molto semplice. Il convertitore automatico da Java a Kotlin incluso nel plugin Kotlin aiuta con i primi passi. `Kotlin Koans`_ offre una guida attraverso le caratteristiche principali della lingua con una serie di esercizi interattivi. .. _Kotlin Koans: https://play.kotlinlang.org/koans/Introduction/Hello,%20world!/Task.kt Strumenti per lo sviluppo Android ================================= Il team di Kotlin offre un set di strumenti per lo sviluppo Android che va oltre le funzionalità linguistiche standard: - `Kotlin Android Extensions`_ è un'estensione per compilatore che ti consente di sbarazzarti delle chiamate findViewById () nel tuo codice e di sostituirle con proprietà sintetiche generate dal compilatore. - `Anko`_ è una libreria che fornisce una serie di wrapper compatibili con Kotlin attorno alle API Android, oltre a una DSL che consente di sostituire i file .xml del layout con il codice Kotlin. .. _Kotlin Android Extensions: https://kotlinlang.org/docs/tutorials/android-plugin.html .. _Anko: http://github.com/kotlin/anko Sintassi di base ================ **Definizione package** ----------------------- Il package va definito all'inizio del file: .. code-block:: Text package my.demo import java.util.* // ... **Definizione funzioni** ------------------------ Funzione con passaggio di due parametri di tipo Int che ritornerà un Int: .. code-block:: Text fun sum(a: Int, b: Int): Int { return a + b } Funzione con nessun valore di ritorno (:file:`void` di Java): .. code-block:: Text fun printSum(a: Int, b: Int): Unit { println("sum of $a and $b is ${a + b}") } volendo :file:`:Unit` si può omettere **Definizione variabili** ------------------------- Le variabili di sola lettura il cui valore può essere assegnato una sola volta vengono dichiarate con la chiave :file:`val`: .. code-block:: Text val a: Int = 1 // assegnazione immediata val b = 2 // assegnazione con tipologia deducibile in questo caso `Int` val c: Int // Indicare la tipologia se la variabili non viene inizializzata c = 3 // assegnazione di valore dopo la dichiarazione Le variabili, invece, il cui valore può essere riassegnato vengono dichiarate con la chiave :file:`var`: .. code-block:: Text var x = 5 // tipo `Int` deducibile x += 1 **Commenti** ------------ I commenti in Kotlin sono come quelli in Java, supportano sia il commento della singola riga che a blocco. A differenza di Java, i commenti di blocco in Kotlin possono essere annidati. .. code-block:: Text // Commento riga singola /* Commento in blocco di più righe */ /* Commento in blocco /* Commento in blocco annidato */ */ **Utilizzo delle stringhe** --------------------------- .. code-block:: Text var a = 1 // aggiunta del nome `a` nel modello `s1`: val s1 = "a is $a" a = 2 // espressione complessa in un modello : val s2 = "${s1.replace("is", "was")}, but now is $a" **Utilizzo delle espressioni condizionali** ------------------------------------------- .. code-block:: Text fun maxOf(a: Int, b: Int): Int { if (a > b) { return a } else { return b } } //L'uso dell'if in una espressione fun maxOf(a: Int, b: Int) = if (a > b) a else b **Utilizzo dei valori nulli e controllo per null** -------------------------------------------------- Bisogna esplicitamente indicare se un valore può ritornare :file:`null`. La funziona ritornerà *null* se non sarà un valore intero: .. code-block:: Text fun parseInt(str: String): Int? { // ... } fun printProduct(arg1: String, arg2: String) { val x = parseInt(arg1) val y = parseInt(arg2) // L'uso di `x * y` restituisce un errore perchè potrebbe contenere valori nulli. if (x != null && y != null) { // x e y vengono automaticamente convetiti in valore non nulli println(x * y) } else { println("'$arg1' o '$arg2' non sono numeri") } } **Utilizzo dei controlli sul tipo e i cast automatici** ------------------------------------------------------- L'operatore :file:`is` controlla se l'espressione è un'istanza di un tipo. Se una variabile viene controllata per un tipo specifico, non è necessario eseguire il cast esplicito: .. code-block:: Text fun getStringLength(obj: Any): Int? { if (obj is String) { // `obj` viene automaticamente tipizzato `String` dopo questo controllo return obj.length } // `obj` è ancora di tipo `Any` fuori dal controllo return null } o fun getStringLength(obj: Any): Int? { if (obj !is String) return null // `obj` è automaticamente tipizzato `String` dopo il controllo return obj.length } o ancora fun getStringLength(obj: Any): Int? { // `obj` viene automaticamente tipizzato a `String` dopo `&&` if (obj is String && obj.length > 0) { return obj.length } return null } **Utilizzo dei cicli** ---------------------- Ciclo :file:`for`: .. code-block:: Text val items = listOf("apple", "banana", "kiwifruit") for (item in items) { println(item) } or val items = listOf("apple", "banana", "kiwifruit") for (index in items.indices) { println("item at $index is ${items[index]}") } Ciclo :file:`while`: .. code-block:: Text val items = listOf("apple", "banana", "kiwifruit") var index = 0 while (index < items.size) { println("item at $index is ${items[index]}") index++ } **Utilizzo dell'espressioni when** ---------------------------------- Le espressioni when sono come degli swith ma più potenti: .. code-block:: Text fun describe(obj: Any): String = when (obj) { 1 -> "One" "Hello" -> "Greeting" is Long -> "Long" !is String -> "Not a string" else -> "Unknown" } **Utilizzo degli intervalli** ----------------------------- Per controllare se un numero appartiene o meno a un intervallo si può utilizzare l'operatore :file:`in`: .. code-block:: Text val x = 10 val y = 9 //controllo del valore x se contenuto nell'intervallo da 1 a y+1 (in questo caso 10) if (x in 1..y+1) { println("fits in range") } //ex. out of range val list = listOf("a", "b", "c") if (-1 !in 0..list.lastIndex) { println("-1 is out of range") } if (list.size !in list.indices) { println("list size is out of valid list indices range, too") } //ciclo su un intervallo for (x in 1..5) { print(x) } //circlo su un intervallo con pregressione for (x in 1..10 step 2) { print(x) } println() for (x in 9 downTo 0 step 3) { print(x) } **Utilizzo delle collezioni** ----------------------------- Cicli su delle collezioni .. code-block:: Text for (item in items) { println(item) } //controlla se la collezione contiene gli oggetti when { "orange" in items -> println("juicy") "apple" in items -> println("apple is fine too") } //utilizzo dell'espressione lambda per filtrare e mappare la collezione: val fruits = listOf("banana", "avocado", "apple", "kiwifruit") fruits .filter { it.startsWith("a") } .sortedBy { it } .map { it.toUpperCase() } .forEach { println(it) } **Creazioni di classi base e le loro istanze** ---------------------------------------------- .. code-block:: Text val rectangle = Rectangle(5.0, 2.0) //non è necessaria la chiave 'new' val triangle = Triangle(3.0, 4.0, 5.0)