# Android ## Conceptos básicos Pedro Joya Máñez --- ### ¿Qué es Android? - Sistema operativo móvil basado en Linux - Para múltiples dispositivos (smart phones, tablets, Google TV, smart wathes, etc.) - Su nombre proviene de la novela de Philip K. Dick llamada "¿Sueñan los androides con ovejas eléctricas?" (Blade Runner) --- ### Versiones - Cada versión principal tiene el nombre de un postre. - En cada versión principal se incrementa la letra inicial del nombre - Cada versión tiene un nombre un número de API asociada - De una misma versión principal puede haber distintas APIs - En el mercado se encuentran dispositivos con distintas versiones (fragmentación) :worried: --- ### Versiones principales (I) | Versión | Nombre | API | Fecha | | :-----: | -------------------------------------------- | :----: | :-----: | | 2.3 | Gingerbread (pan de jengibre) | 9 | 12/2010 | | 4.0 | Ice cream sandwich, ICS (sandwich de helado) | 14 | 10/2011 | | 4.1 | Jelly Bean (gragea) | 16 | 07/2012 | | 4.4 | KitKat (barrita de chocolate) | 19 | 10/2013 | | 5.0 | Lollypop (piruleta) | 21 | 11/2014 | --- ### Versiones principales (II) | Versión | Nombre | API | Fecha | | :-----: | -------------------------------------------- | :----: | :-----: | | 6.0 | Marshmellow (nube, esponjita) | 23 | 10/2015 | | 7.0 | Nougat (turrón) | 24 | 08/2016 | | 8.0 | Oreo (galleta) | 26 | 08/2017 | | 9.0 | Pie | 28 | 08/2018 | | 10.0 | Q | 29 | ? | --- ### Distribución actual (Google) ![](https://chart.googleapis.com/chart?chf=bg%2Cs%2C00000000&chd=t%3A0.3%2C0.3%2C3.2%2C6.9%2C14.5%2C16.9%2C19.2%2C28.3%2C10.4&chco=c4df9b%2C6fad0c&chl=Gingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat%7CLollipop%7CMarshmallow%7CNougat%7COreo%7CPie&cht=p&chs=500x250) - Con la API 21 (Lollypop) se abarca más del 90% de los dispositivos. La emplearemos como API mínima --- ### Entorno de desarrollo - Sistema operativo: Windows, Linux, Mac OS - Lenguaje de programación: Java o Kotlin. No compatible al 100% con Java 8. Instalar JDK 8. - IDE: Android Studio (IntelliJ personalizado) - Android SDKs de APIs (preinstaladas con Android Studio) - Emulador y dispositivos virtuales o dispositivo real (instalar drivers) --- ### Nuestro primer proyecto ![](https://media.giphy.com/media/AOSwwqVjNZlDO/giphy.gif) --- ### Estructura básica de un proyecto - Directorio del módulo principal (app) - Subdirectorio de código fuente (app/src/main/java) - Subdirectorio de recursos (app/src/main/res) - Manifiesto (app/src/main) - Fichero de configuración del módulo (app/build.gradle) - Fichero de configuración del proyecto (build.gradle) --- ### Especificación de layout - Definición de la interfaz de usuario mediante XML - Es un árbol de vistas - Algunas vistas (ViewGroup) pueden contener otras vistas - Para cada vista se especifican atributos - Algunos atributos son heredados del ViewGroup en el que se encuentre - Se define dentro de res/layout --- ### Ejemplo de layout ```xml= <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Name"/> <EditText android:id="@+id/txtName" android:layout_width="match_parent" android:layout_height="wrap_content"/> <CheckBox android:id="@+id/chkPolite" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:checked="false" android:text="Politely"/> <Button android:id="@+id/btnGreet" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:text="Greet"/> </LinearLayout> ``` --- ### XML Namespaces ```xml= <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ... > ``` - `xmlns:android` define el namespace donde están definidos los atributos posibles - Sólo se pone en el elemento raíz - Los atributos se referencian usando el namespace `android:` - Hay otros namespaces que veremos más adelante --- ### Anchura y altura ```xml= <EditText ... android:layout_width="match_parent" android:layout_height="wrap_content"/> ``` - Atributos obligatorios en todas las vistas - `wrap_content` para solo lo necesario para envolver el contenido - `match_parent` para todo lo que el padre le deje --- ### El ; es opcional ```java= // JAVA String name = "Baldomero"; ``` ```kotlin= // KOTLIN val name: String = "Baldomero" ``` * En Kotlin el ; es opcional, excepto en un caso específico de los enums :scream: :clap: :dancer: --- ### val vs. var ```java= // JAVA final String name = "Baldomero"; int age = 45; ``` ```kotlin= // KOTLIN val name: String = "Baldomero" var age: Int = 45 ``` - val define una variable que no puede referenciar ningún otro objeto en el futuro. - var define una varible que puede referenciar distintos objetos a lo largo de su vida --- ### Inferencia de tipos ```java= // JAVA <10 final String name = "Baldomero"; // JAVA 10 var name = "Baldomero"; ``` ```kotlin= // KOTLIN var name = "Baldomero" ``` - Tipo inferido (deducido) a partir del tipo de la expresión de inicialización - Lenguaje fuertemente tipado de tipo estático, aunque haya sido inferido (tiempo de compilación) --- ### Tipos referenciales, no primitivos ```kotlin= // KOTLIN val value: Int = 146 val percent = value.coerceIn(0, 100) ``` - No exiten los tipos primitivos, todos son clases. - Internamente se usará un tipo primitivo cuando sea posible, con boxing y unboxing automático - No hay conversión automática de tipos numéricos, sino funciones de conversión explícita en los tipos, como toLong(), toInt(), etc. --- ### Template Strings (interpolación) ```java= // JAVA final String s = "abc"; System.out.println(s + ".length is " + s.length()); ``` ```kotlin= // KOTLIN val s = "abc" println("$s.length is ${s.length}") ``` - $variable para interpolar el valor de una variable - ${expresion} para interpolar el valor de cualquier expresión --- ### Raw Strings ```java= // JAVA final String artist = "Chiquito de la Calzada"; final String saying = "No te digo trigo...\n" + "por no llamarte Rodrigo\n" + "(" + artist + ")"; ``` ```kotlin= // KOTLIN val artist = "Chiquito de la Calzada" val saying = """ |No te digo trigo |por no llamarte Rodrigo |($artist) """.trimMargin() ``` - Literal de cadena sin caracteres de escape (\n, \t, ...) - Puede contener interpolación. - Se propuso para Java 12, pero fue pospuesto. --- ### if else es una expresión ```kotlin= // KOTLIN val max = if (a > b) { print("a es el máximo") a } else { print("b es el máximo") b } ``` - Las estructura if else es una expresión, que se evalúa al valor al que se evalúa la rama ejecutada - Una rama se evalúa al valor al que se evalúa la última expresión de la rama --- ### No hay operador ternario ```java= // JAVA final int max = a > b ? a : b; ``` ```kotlin= // KOTLIN val max = if (a > b) a else b ``` - En este caso Kotlin puede resultar más verboso que Java :confused: --- ### Estructura for ```java= // JAVA for (int i = 1; i <= 10; i++) System.out.println(i); ``` ```kotlin= // KOTLIN for (i in 1..10) println(i) ``` - Kotlin no posee la estructura for tradicional de Java - Sólo for sobre iterador (for each) - Podemos usar un literal de rango de valores para iterar sobre él --- ### Range ```java= // JAVA for (int i = 1; i < 10; i++) System.out.println(i); for (int i = 6; i >= 0; i-=2) System.out.println(i); ``` ```kotlin= // KOTLIN for (i in 1 until 10) println(i) for (i in 6 downTo 0 step 2) println(i) ``` - La clase Range modela un rango de datos y posee un iterador - Podemos usar los métodos until, downTo y step para crear el rango adecuado --- ### when como switch mejorado ```kotlin= when (input) { 1 -> println("Uno") 7, 8 -> println("Siete u ocho") in 10..19 -> println("Decena") is String -> println("Cadena de ${input.length}") else -> { println("Otra cosa") println("Lo sentimos") } } ``` - No necesita break - Más de un valor de comparación en cada rama - Comprobación de pertenencia o no a un rango, array o lista - Comprobación de pertenencia o no a un tipo --- ### when es una expresión ```kotlin= val semester = when (month) { in 1..6 -> "Primer semestre" in 7..12 -> "segundo semestre" else -> "Mes no válido" } ``` - Devuelve el valor al que se evalúa la rama seleccionada, que corresponde al valor al que se evalúa su última expresión - Debe ser exhaustivo (abarcar todas las posibilidades) - Java 12 incorpora una versión preliminar de switch mejorado con funcionalidad similar --- ### when como if else if ```java= // JAVA if (x.isOdd()) System.out.println("x es impar"); else if (x.isEven()) System.out.println("x es par"); else System.out.println("x está indecisa"); ``` ```kotlin= // KOTLIN when { x.isOdd() -> println("x is impar") x.isEven() -> println("x is par") else -> println("x está indecisa") } ``` - Las ramas se consideran expresiones booleanas y se ejecutará la primera que sea verdadera - También puede usarse como expresión --- ### Hydration break ![](https://media.giphy.com/media/dlbcP3ngz7c6j1kOW2/giphy.gif) --- ### Definición de funciones ```java= // JAVA String greet(String name, String message) { return message + ", " + name; } ``` ```kotlin= // KOTLIN fun greet(name: String, message: String): String { return "$message, $name" } ``` * fun is :smile: * El tipo de retorno se coloca al final, pero puede ser inferido --- ### Funciones que no retornan "nada" ```java= // JAVA void greet(String name, String message) { System.out.println(message + ", " + name); } ``` ```kotlin= // KOTLIN fun greet(name: String, message: String) { println("$message, $name") } ``` - El tipo de retorno es Unit, pero podemos omitirlo - Unit es un tipo, no una palabra reserva como void - La función retorna en realidad el objeto Unit (singleton) --- ### Funciones con una única expresión ```java= // JAVA String greet(String name, String message) { return message + ", " + name; } ``` ```kotlin= // KOTLIN fun greet(name: String, message: String) = "$message, $name" ``` - El tipo de retorno es inferido a partir del tipo de la expresión, aunque puede ser especificado explícitamente --- ### Argumentos con valores por defecto ```java= // JAVA String greet(String name) { return greet(name, "Hola"); } String greet(String name, String message) { return message + ", " + name; } ``` ```kotlin= // KOTLIN fun greet(name: String, message: String = "Hola") = "$message, $name" ``` - Permiten mejorar una API existente fácilmente - El valor por defecto de un parámetro puede usar el valor de un argumento anterior - En Java se simulan mediante sobrecarga de métodos --- ### Named arguments ```kotlin= // KOTLIN fun greet(name: String = "Baldomero", message: String = "Hola") = "$message, $name" println(greet(message="Quillo que")) println(greet(message="Quillo que", name="Germán Ginés")) println(greet("Germán Ginés", message="Quillo que")) ``` * Permite especificar sólo algunos argumentos * Permite cambiar el orden de los argumentos * Puede usarse en conjunción con el paso de argumentos posicional, empezando por éste * Esta funcionalidad NO existe en Java --- ### varargs y spread operator ```kotlin= // KOTLIN fun printStrings(vararg strings: String) { for (string in strings) println(string) } val names = arrayOf("Baldomero", "Germán Ginés") printStrings("Quillo que", *names, "Na aquí") ``` - El operador * (operador de dispersión) delante de un array retorna la lista de valores del array separados por coma , --- ### Top level functions and properties ```kotlin= // KOTLIN // Directamente en un fichero, fuera de cualquier clase const val PI = 3.14 var isUserLoggedIn: Boolean = false fun greet(name: String) { println("Hola $name") } fun main() { greet("Baldomero") isUserLoggedIn = true println("El número PI vale $PI") } ``` - Funciones fuera de cualquier clase. Ejemplo: main - Propiedades fuera de cualquier clase. - const para constantes conocidas en tiempo de compilación, que el compilador usará de modo inline --- ### Extension functions ```java= // JAVA public static String shout(String receiver) { return "¡" + receiver.toUpperCase() + "!"; } String greet = "Quillo que"; System.out.println(StringsUtils.shout(greet)); ``` ```kotlin= // KOTLIN fun String.shout(): String = "¡${this.toUpperCase()}!" val greet = "Quillo que" println(greet.shout()) ``` - Llamada como si fuera un miembro de una determinada clase. - El IDE sugiere la función al escribir un . tras una variable de dicho tipo :dancer: - Dentro de la función, this corresponde al receptor --- ### Lambdas ```kotlin= // KOTLIN fun operateAndPrint(x: Int = 0, action: (Int) -> Int): Int { val result = action(x) // action.invoke(x) println("Result: $result") return result } val increm3 = { x: Int -> x + 3 } operateAndPrint(2, increm3) ``` - Tipos función (vs. interf. func. de Java) - Expresión lambda = literal de objeto función, almacenable y pasable como argumento - Una lamba se ejecuta mediante el operador () o llamando a su método invoke() - La expresión lambda se evalúa al valor al que se evalúe la última expresión de su cuerpo --- ### Lambdas como argumento ```kotlin= // KOTLIN fun operateAndPrint(x: Int = 0, action: (Int) -> Int): Int { val result = action(x) println("Result: $result") return result } operateAndPrint(2, { x -> x + 3}) operateAndPrint(2) { x -> x + 3} operateAndPrint { x -> x + 3 } operateAndPrint { it + 3 } ``` - Inferencia de tipos en los parámetros de la lambda - Si lambda es último argumento, sacar de los () - Si lambda es único argumento, nos ahorramos los () - Si lambda tiene un solo argumento, usar it en cuerpo --- ### Smart cast ```java= // JAVA if (obj instanceof String) System.out.println(((String) obj).length()); ``` ```kotlin= // KOTLIN if (obj is String) println(obj.length) ``` - El compilador hace el cast internamente dentro de la rama :bulb: - Sólo puede aplicarse si la variable no puede cambiar entre la comprobación y el acceso - También en ramas de la estructura when y en comprobación de no null --- ### Tipos nullable y no nullables ```kotlin= // KOTLIN var name: String? = "Baldomero" var sirname: String = "Llegate Ligero" name = null if (name != null) println(name.length) ``` - Nulabilidad dentro del sistema de tipos. - Detección de errores relacionados con null en tiempo de compilación :clap: - Tipo? permite null, Tipo no permite null. Tipo es un subtipo de Tipo? - Smart cast de Tipo? a Tipo tras comprobación de que la variable no es null --- ### Jerarquía de tipos ![](https://i.imgur.com/K4HzWGD.png) - Any es similar a Object - Cada tipo no nullable es subtipo del correspondiente nullable - Nothing es subtipo de todos los tipos --- ### Nothing y throw como expresión ```kotlin= // KOTLIN fun fail(message: String): Nothing { throw IllegalStateException(message) } val fruitPerGlass: Int = if (glassesSold > 0) orangesUsed / glassesSold else throw NoGlassesSold() ``` - El tipo Nothing indica que la función nunca terminará satisfactoriamente y por tanto no retornará - Es subtipo de todos los tipos - throw es una expresión que retorna Nothing --- ### Operador de acceso seguro ```java= // JAVA final Integer length = nickname != null ? nickname.length() : null; final String name = nickname != null ? nickname.toUpperCase() : null; ``` ```kotlin= // KOTLIN val length: Int? = nickname?.length val name = nickname?.toUpperCase() ``` - No se permite usar el operador . con variables de tipo nullable (acceso seguro) - Se debe usar ?. en vez de . para acceder a propiedades y métodos - Se evalúa a null si la variable contiene null --- ### Operador elvis ```java= // JAVA final int length = nickname != null ? nickname.length() : 0; ``` ```kotlin= // KOTLIN val length: Int = nickname?.length ?: 0 ``` - Devuelve la expresión de la izquierda si ésta es distinta de null y la de la derecha en caso contrario - Funciona como un valor por defecto si la expresión es null --- ### Operador bang bang ```java= // JAVA String name = "Baldomero"; final Integer length = name.length(); ``` ```kotlin= // KOTLIN var name: String? = "Baldomero" val lenght = name!!.length ``` - Produce NullPointerException si la variable es null - Se recomienda sólo usarlo cuando estemos completamente seguros de que no es null. --- ### let ```java= // JAVA final String name = "Baldomero"; if (name != null) { System.out.println("Name: " + name); } ``` ```kotlin= // KOTLIN val name: String? = "Baldomero" name?.let { println("Name: $it") } ``` - Extension function, sobre cualquier tipo, que recibe como parámetro una expresión lambda - La lambda es ejecutada pasándole como argumento el objeto sobre el que se ejecuta let - Retorna el valor retornado por la expresión lambda. --- ### also ```java= // JAVA final Student student = new Student(); student.setAge(45); student.setAddress("c/ Avda. Duque de Rivas, 1") ``` ```kotlin= // KOTLIN val student: Student = Student().also { it.age = 45 it.address = "c/ Avda. Duque de Rivas, 1" } ``` - Similar a let pero retorna el propio objeto sobre el que se ejecuta also - Se puede usar para configurar un objeto al crearlo antes de retornarlo (patrón builder) --- ### Hydration break ![](https://media.giphy.com/media/dlbcP3ngz7c6j1kOW2/giphy.gif) --- ### Constructor primario ```java= // JAVA final class Student extends Person { private final boolean isRepeater; private int age; public Student(@NotNull String name, boolean isRepeater, int age) { super(name); this.isRepeater = isRepeater; this.age = age; } } ``` ```kotlin= // KOTLIN class Student(name: String, val isRepeater: Boolean, var age) : Person(name) ``` - Constructor primario definido en primera linea - Llamada al constructor primario de la superclase al definir la herencia --- ### Bloque de inicialización ```java= // JAVA final class Student extends Person { private final boolean isRepeater; private int age; public Student(@NotNull String name, boolean isRepeater, int age) { super(name); this.isRepeater = isRepeater; this.age = age; // Código de inicialización... } } ``` ```kotlin= // KOTLIN class Student(name: String, val isRepeater: Boolean, var age: Int) : Person(name) { init { // Código de inicialización... } } ``` - Código de inicialización en bloque init. --- ### Instanciación ```java= // JAVA final Student student = new Student("Baldomero", false, 23); ``` ```kotlin= // KOTLIN val student = Student("Baldomero", false, 23) ``` - No existe el operador new --- ### Concepto de propiedad ```java= // JAVA final class Student extends Person { private final boolean isRepeater; private int age; private int grade; public Student(@NotNull String name, boolean isRepeater, int age) { super(name); this.isRepeater = isRepeater; this.age = age; } public boolean isRepeater() { return isRepeater; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getGrade() { return grade; } public void setGrade(int grade) { this.grade = grade; } } ``` - Al conjunto formado por el campo (field), el getter y el setter se le conoce como propiedad --- ### Propiedades en Kotlin ```kotlin= // KOTLIN class Student(name: String, val isRepeater: Boolean, var age: Int) : Person(name) { var grade: Int = 0 } ``` - Definidas directamente en el constructor primario o en el cuerpo de la clase - Los parámetros del constructor sin val ni var NO crean propiedades. Son valores para inicialización de otras propiedades --- ### Getter y setters personalizados ```kotlin= // KOTLIN class Student(name: String, val isRepeater: Boolean, var age: Int) : Person(name) { var grade: Int = 0 set(value) { if (value >= 0) field = value else throw IllegalArgumentException() } val gradeDescription: String get() = when(grade) { in 0..4 -> "Mal" in 5..7 -> "Aceptable" in 8..10 -> "Bien" else -> "No válida" } } ``` - field representa el campo interno creado - Podemos crear propiedades que no tienen ningún campo asociado --- ### Acceso a propiedades ```java= // JAVA final Student student = new Student("Baldomero", false, 25); System.out.println(student.getName()); student.setGrade(8); System.out.println(student.getGradeDescription()); ``` ```kotlin= // KOTLIN val student = Student("Baldomero", false, 25) println(student.name) student.grade = 8 println(student.gradeDescription) ``` - Se usa el operador . para acceder a una propiedad, tanto para lectura como para escritura. --- ### Notación infix ```java= // JAVA public final class Pizza { public final void add(@NotNull String ingredient) { System.out.println(ingredient + " added to pizza"); } } Pizza pizza = new Pizza(); pizza.add("Cheese"); ``` ```kotlin= // KOTLIN class Pizza { infix fun add(ingredient: String) { println("$ingredient added to pizza") } } val pizza = Pizza() pizza add "Cheese" ``` - Notación de operaciones aritméticas binarias - Método o extension function con un único parámetro --- ### Concepto de data class ```java= // JAVA public final class User { @NotNull private final String name; private final int age; public User(@NotNull String name, int age) { ... } @NotNull public final String getName() { ... } public final int getAge() { ... } @NotNull public String toString() { ... } public int hashCode() { ... } public boolean equals(@Nullable Object var1) { ... } // ... } ``` - Clase cuyo propósito principal es contener datos. Habitualmente implementan equals(), hashCode() y toString(). --- ### Data class en Kotlin ```kotlin= data class User(val name: String, val age: Int) ``` - Implementaciones por defecto del constructor, getters de propiedades, setters para propiedades var, toString(), hashCode(), equals() - Se puede implementar explícitamente toString(), hashCode() y equals() en el cuerpo de la clase - Implementación del método copy() para crear un nuevo objeto a partir de uno existente - Implementación de métodos para desestructuración: component1(), component2(), etc. --- ### Desestructuración ```java= User jane = new User("Jane", 35); String name = jane.component1(); int age = jane.component2(); ``` ```kotlin= val jane = User("Jane", 35) val (name, age) = jane ``` - Asignación a lista de variables individuales, desde propiedades de un objeto (o elementos de colección) --- ### Delegación ```kotlin= interface Base { fun print() } // Cuando se llame al método print() sobre un objeto de la clase // Derived se llamará automáticamente al método print() de objeto b. class Derived(b: Base) : Base by b { // Otros métodos } ``` - Delegación y composición vs. herencia - El compilador generará automáticamente en la clase Derived el método print(), que internamente llamará a b.print() --- ### Object ```java= public final class RepositoryImp implements Repository { public static final RepositoryImp INSTANCE = new RepositoryImp(); private RepositoryImp() { } // ... } RepositoryImp repository = RepositoryImp.INSTANCE; ``` ```kotlin= object RepositoryImp : Repository { // ... } val repository = RepositoryImp.INSTANCE ``` - Patrón singleton en modo eager con solo usar object en vez de class --- ### Sealed classes ```kotlin= sealed class Post // Las clases hijas pueden ser clases normales, data classes e incluso objects. data class Status(var text: String) : Post() data class Image(var url: String, var caption: String) : Post() data class Video(var url: String, var timeDuration: Int, var encoding: String): Post() object Headline : Post() ``` - Clase que sólo puede tener unas determinadas clases hijas predefinidas - Es abstracta por definición - Tanto la clase padres como las hijas deben estar definidas en el mismo fichero --- ### No exite la palabra reservada static ```java= // JAVA class Person { public static void callMe() { } } Person.callMe(); ``` ```kotlin= // KOTLIN class Person { companion object { fun callMe() { } } } Person.callMe() ``` - Clases de utilidad no necesarias (extension functions y top level functions) - Companion object asociado a una clase --- ### Sobrecarga de operadores ```kotlin= // KOTLIN data class Point(var x: Double, var y: Double) { operator fun plus(point: Point) = Point(x + point.x, y + point.y) } val p1 = Point(2.9, 5.0) val p2 = Point(2.0, 7.5) val p3 = p1 + p2 ``` - Conjunto predefinido de operadores con representación simbólica; +, - , ... - Al usar un operador internamente se llama al método asociado a él: a + b se traduce a a.plus(b) - Podemos definir el método asociado a un determinado operador en nuestras clases --- ### Asociaciones de operadores | Expresión | Se traduce a | | ----------- | --------------------------------- | | a + b, a - b, a * b | a.plus(b), a.minus(b), a.times(b) | | a..b, a in b | a.rangeTo(b), b.contains(a) | | a[i], a[i] = b | a.get(i), a.set(i, b) | | a() | a.invoke() | | a == b | a?.equals(b) ?: (b === null) | | a > b | a.compareTo(b) > 0 | | a += b | a.plusAssign(b) | --- ### Colecciones mutables e inmutables ```kotlin= // KOTLIN val inmutableList = listOf(1, 2, 3) val mutableList = mutableListOf(1, 2, 3) mutableList.add(4) ``` - Interfaces distintas para colecciones inmutables y mutables --- ### Trabajo funcional con colecciones ```java= // JAVA 9 List.of(4, -1, 2, -8) .stream() .filter(it -> it > 0) .map(it -> it * 2) .forEach(System.out::println); ``` ```kotlin= // KOTLIN listOf(4, -1, 2, -8) .filter { it > 0 } .map { it * 2 } .forEach(::println) ``` - Métodos de filtrado, transformación, reducción, etc. directamente en las colecciones - Por defecto eager aunque puede convertirse en lazy - lambdas y referencias a métodos --- ### Otros cambios - Las clases y los métodos son públicos por defecto - Las clases y los métodos son final por defecto (usar open para abrirlos) - Las clases internas son static por defecto - protected es más restrictivo: sólo subclases - Modificador de acceso internal para visibilidad a nivel de módulo - Un fichero puede tener más de una clase pública - No existen las checked exceptions. Tampoco throws --- ## En resumen... --- ![](https://i.imgur.com/vRZGsFJ.jpg) --- ### Referencias - Web oficial: [https://kotlinlang.org/](https://kotlinlang.org/) - Playground: [https://play.kotlinlang.org](https://play.kotlinlang.org) - Learn Kotlin: [https://kotlinlang.org/docs/reference/](https://kotlinlang.org/docs/reference/) --- ![](https://i.imgur.com/J9Etqb4.jpg)
{"metaMigratedAt":"2023-06-14T22:19:45.007Z","metaMigratedFrom":"YAML","title":"Conceptos básicos de Android","breaks":true,"description":"Conceptos básicos de Android","slideOptions":"{\"theme\":\"beige\",\"transition\":\"slide\",\"mouseWheel\":false,\"touch\":true,\"controlsLayout\":\"edges\",\"hideAddressBar\":true,\"keyboard\":true,\"overview\":false}","contributors":"[{\"id\":\"b3c7cbd8-c6bb-44e9-8380-34b896c77ea7\",\"add\":6079,\"del\":2181}]"}
    251 views