# Table of Contents - [Introducción | Dart](#introducci-n-dart) - [Objetivos | 1. Introducción a Flutter](#objetivos-1-introducci-n-a-flutter) - [1. Introducción | 1. Introducción a Flutter](#1-introducci-n-1-introducci-n-a-flutter) - [Referencias y Recursos | 1. Introducción a Flutter](#referencias-y-recursos-1-introducci-n-a-flutter) - [Plataformas | 1. Introducción a Flutter](#plataformas-1-introducci-n-a-flutter) - [Paquetes y bibliotecas | 1. Introducción a Flutter](#paquetes-y-bibliotecas-1-introducci-n-a-flutter) - [Casos de uso | 1. Introducción a Flutter](#casos-de-uso-1-introducci-n-a-flutter) - [¿Cómo funciona Flutter? | 1. Introducción a Flutter](#-c-mo-funciona-flutter-1-introducci-n-a-flutter) - [Características destacables de Flutter | 1. Introducción a Flutter](#caracter-sticas-destacables-de-flutter-1-introducci-n-a-flutter) - [2. Instalación del Flutter SDK | 1. Introducción a Flutter](#2-instalaci-n-del-flutter-sdk-1-introducci-n-a-flutter) - [Instalación rápida | 1. Introducción a Flutter](#instalaci-n-r-pida-1-introducci-n-a-flutter) - [Instalación manual | 1. Introducción a Flutter](#instalaci-n-manual-1-introducci-n-a-flutter) - [Ejemplo, Flutter in Ubuntu: Step by Step. | 1. Introducción a Flutter](#ejemplo-flutter-in-ubuntu-step-by-step-1-introducci-n-a-flutter) - [3. Primera aplicación en Flutter | 1. Introducción a Flutter](#3-primera-aplicaci-n-en-flutter-1-introducci-n-a-flutter) - [Desde el DartPad | 1. Introducción a Flutter](#desde-el-dartpad-1-introducci-n-a-flutter) - [Desde Android Studio | 1. Introducción a Flutter](#desde-android-studio-1-introducci-n-a-flutter) - [4. Conceptos fundamentales en Flutter | 1. Introducción a Flutter](#4-conceptos-fundamentales-en-flutter-1-introducci-n-a-flutter) - [Hot Reload - Hot Restart - Full Restart | 1. Introducción a Flutter](#hot-reload-hot-restart-full-restart-1-introducci-n-a-flutter) - [Desde el Terminal | 1. Introducción a Flutter](#desde-el-terminal-1-introducci-n-a-flutter) - [Widgets | 1. Introducción a Flutter](#widgets-1-introducci-n-a-flutter) - [6. Tips & Tricks | 1. Introducción a Flutter](#6-tips-tricks-1-introducci-n-a-flutter) - [Herramientas para debugging. Logs | 1. Introducción a Flutter](#herramientas-para-debugging-logs-1-introducci-n-a-flutter) - [Stateless widget | 1. Introducción a Flutter](#stateless-widget-1-introducci-n-a-flutter) - [Estructura de una Aplicación Flutter | 1. Introducción a Flutter](#estructura-de-una-aplicaci-n-flutter-1-introducci-n-a-flutter) - [Ciclo de Vida | 1. Introducción a Flutter](#ciclo-de-vida-1-introducci-n-a-flutter) - [5. Recomendaciones (best practices) | 1. Introducción a Flutter](#5-recomendaciones-best-practices-1-introducci-n-a-flutter) - [Desde Visual Studio Code | 1. Introducción a Flutter](#desde-visual-studio-code-1-introducci-n-a-flutter) - [Ciclo de Vida de los Widgets | 1. Introducción a Flutter](#ciclo-de-vida-de-los-widgets-1-introducci-n-a-flutter) - [Stateful widget | 1. Introducción a Flutter](#stateful-widget-1-introducci-n-a-flutter) - [Ejemplo de uso de keys | 1. Introducción a Flutter](#ejemplo-de-uso-de-keys-1-introducci-n-a-flutter) - [Ciclo de vida de la aplicación | 1. Introducción a Flutter](#ciclo-de-vida-de-la-aplicaci-n-1-introducci-n-a-flutter) - [Referencias | Dart](#referencias-dart) - [Responding to widget lifecycle events, Keys | 1. Introducción a Flutter](#responding-to-widget-lifecycle-events-keys-1-introducci-n-a-flutter) - [Control de Flujo: Condiciones y Bucles | Dart](#control-de-flujo-condiciones-y-bucles-dart) - [Conceptos Básicos | Dart](#conceptos-b-sicos-dart) - [Resumen tipos de datos | Dart](#resumen-tipos-de-datos-dart) - [Dart Core Libraries | Dart](#dart-core-libraries-dart) - [Colecciones | Dart](#colecciones-dart) - [String | Dart](#string-dart) - [dynamic vs Object | Dart](#dynamic-vs-object-dart) - [List | Dart](#list-dart) - [Set | Dart](#set-dart) - [Programación funcional | Dart](#programaci-n-funcional-dart) - [Tipos de datos básicos | Dart](#tipos-de-datos-b-sicos-dart) - [Funciones | Dart](#funciones-dart) - [Variables | Dart](#variables-dart) - [Packages and Libraries | Dart](#packages-and-libraries-dart) - [Concurrencia-Programación asíncrona | Dart](#concurrencia-programaci-n-as-ncrona-dart) - [Map | Dart](#map-dart) - [Operadores | Dart](#operadores-dart) - [Funciones | Dart](#funciones-dart) - [Exceptions | Dart](#exceptions-dart) - [Programación asíncrona | Dart](#programaci-n-as-ncrona-dart) - [Guia para escribir código Dart standard, claro y efectivo | Dart](#guia-para-escribir-c-digo-dart-standard-claro-y-efectivo-dart) - [Colecciones | Dart](#colecciones-dart) - [Excepciones | Dart](#excepciones-dart) - [Clases | Dart](#clases-dart) - [Clases abstractas | Dart](#clases-abstractas-dart) - [Variables y métodos de clase (static) | Dart](#variables-y-m-todos-de-clase-static-dart) - [Conceptos básicos | Dart](#conceptos-b-sicos-dart) - [Programación básica | Dart](#programaci-n-b-sica-dart) - [Tipos enumerados | Dart](#tipos-enumerados-dart) - [Futures, async/ await | Dart](#futures-async-await-dart) - [Métodos de extensión | Dart](#m-todos-de-extensi-n-dart) - [Interfaces implícitas | Dart](#interfaces-impl-citas-dart) - [Clases Callable (Callable objects) | Dart](#clases-callable-callable-objects-dart) - [Mixins | Dart](#mixins-dart) - [Herencia y sobrescritura. Propiedades get y set. | Dart](#herencia-y-sobrescritura-propiedades-get-y-set-dart) - [Constructores | Dart](#constructores-dart) - [Clases | Dart](#clases-dart) - [Conceptos básicos | Dart](#conceptos-b-sicos-dart) --- # Introducción | Dart Dart (originalmente llamado Dash) es un lenguaje de programación de **código** **abierto**, **desarrollado** por **Google** y presentado oficialmente en la conferencia _goto_; en Aarhus, Dinamarca el 10 de octubre de **2011**. [_wikipedia_](https://en.m.wikipedia.org/wiki/Dart_(programming_language)) _: Dart es un lenguaje de programación de propósito general originariamente desarrollado por Google y después aprobado como estándar por la Ecma (ECMA-408). Dart se emplea para construir aplicaciones para móviles, servidores, webs y también para internet de las cosas (IoT). Dart es de código abierto y está bajo la licencia BSD._ #### [](https://ecm-pmdm-flutter.gitbook.io/dart#intenciones-iniciales) Intenciones iniciales * Con Dart, google buscaba inicialmente ser una alternativa moderna a **JavaScript** para la programación web, querían incluirlo en Chrome (causando cierto nerviosismo entre los desarrolladores). * Finalmente, en 2015 se optó por transpilar (transcompile) Dart a JavaScript y actualmente cuenta con múltiples opciones de compilación. ### [](https://ecm-pmdm-flutter.gitbook.io/dart#caracteristicas) Características Algunas de sus características son: * Dart es **multiparadigma**: imperativo, orientado a objetos, reflectivo, funcional y de herencia simple. * **Sintaxis** similar al lenguaje **C** que puede **transpilarse** a lenguaje _**JavaScript**_. * Soporta: interfaces, mixins, clases abstractas, genéricos, tipado estático, **tipado** **opcional**, y mucho más. * El código de Dart es _**single**_ _**threaded**_. La **concurrencia** se implementa con _**isolates**_ que son unidades de ejecución independientes pero que no comparten nunca estado. Los _isolates_ se comunican con el paso de mensajes. * Dart es **null-safe**: por defecto, las variables no pueden tener un valor _null_ a no ser que lo digamos explícitamente. Dart és **multiplataforma**, tanto para dispositivos **móviles**, **web**, **escritorio** y dispositivos **embebidos**. ![](https://ecm-pmdm-flutter.gitbook.io/dart/~gitbook/image?url=https%3A%2F%2F1551469701-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FsGv3FSfnl3pEE6ftH9Ys%252Fuploads%252FV0n9m8k9AQX8bDfN3nLw%252Fimage.png%3Falt%3Dmedia%26token%3Dcaa7fc9d-2d1f-4476-b4b0-ba7502ee7354&width=768&dpr=4&quality=100&sign=3f6a9325&sv=2) Además: * Utiliza un **compilador AOT (Ahead-of-Time):** Se compila todo el código entero a nativo antes de la ejecución. * Durante el desarrollo, permite realizar un **hot reload** que permite ver de forma **instantánea** los cambios realizados en la aplicación. * Independientemente de la plataforma o cómo se compile, la ejecución del código requiere un **runtime**: Utiliza una máquina virtual llamada **Dart VM** (gestión de memoria, garbage collector, gestión de isolates, etc) * Las **aplicaciones** de **Flutter** utilizan Dart como lenguaje de desarrollo. ### [](https://ecm-pmdm-flutter.gitbook.io/dart#herramientas-para-programar-con-dart) Herramientas para programar con Dart * **Desde la Máquina Local:** Para desarrollar y ejecutar una aplicación de Dart localmente en tu máquina, necesitas el **SDK** **de** **Dart** ([Dart installation website](https://www.dartlang.org/tools/sdk#install) ) y un editor de texto o un **IDE** con el **plugin** **Dart**: * [IntelliJIDEA](https://www.jetbrains.com/help/idea/dart.html) * [Visual Studio Code](https://code.visualstudio.com/) * [Atom](https://atom.io/) * [Eclipse with the Dartboard plugin](https://github.com/eclipse/dartboard) , etc. * **Desde la Web:** Dart también proporciona una **interfaz** **web** para escribir y probar código Dart: [https://dartpad.dev/](https://dartpad.dev/) #### [](https://ecm-pmdm-flutter.gitbook.io/dart#ejemplo-de-un-programa-en-dart) Ejemplo de un programa en Dart: Copy void main() { print('Hello World!!!'); } [![Logo](https://ecm-pmdm-flutter.gitbook.io/dart/~gitbook/image?url=https%3A%2F%2Fdartpad.dev%2Ficons%2FIcon-192.png&width=20&dpr=4&quality=100&sign=d65dae74&sv=2)DartPaddartpad.dev](https://dartpad.dev/embed-dart.html?id=c60e27faee3ebf82a4839b04d3be5cb3&theme=dark) Pulsa en la imagen para abrir el código anterior en el editor web DartPad Al igual que en Java, C o PHP, todas las sentencias en Dart se cierran con punto y coma. [NextReferencias](https://ecm-pmdm-flutter.gitbook.io/dart/referencias) Last updated 11 months ago --- # Objetivos | 1. Introducción a Flutter * Introducir las **características** más destacables de Flutter * Descargar e instalar **Flutter** **SDK** * Configurar el **plugin** de **Flutter** (Android Studio/IntelliJ / Visual Studio Code) * Crear y ejecutar la **primera** **aplicación** en **Flutter** * Estudiar los **conceptos** fundamentales en Flutter [NextReferencias y Recursos](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos) Last updated 11 months ago --- # 1. Introducción | 1. Introducción a Flutter La diversidad de plataformas que tenemos actualmente: móvil, web, escritorio,..., etc. hace que sea cada vez más interesante la posibilidad de **escribir** el **código** de la aplicación **una** **sola** **vez** y **desplegarla** en **múltiples** **plataformas** (cross-platform) por el **ahorro** de **tiempo** y **esfuerzo** que supone. Las aplicaciones más exitosas, Gmail, Netflix..., suelen tener una imagen de marca por lo que proporcionan una **UI** con el **mismo** **diseño** en todas las plataformas (iOS, Android,..) **Flutter** fue **creado** por Google en **2015** y presentó oficialmente la **version 1.0** en Diciembre de **2018**. Es uno de los **frameworks** **multiplataforma** más recientes y que ha ganado mucha **popularidad** entre los desarrolladores. En la siguiente **gráfica** podemos los frameworks móviles cross-platform más usados: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252Fw3SuPdPdpYdfd0C5YzS0%252Fimage.png%3Falt%3Dmedia%26token%3D7375e7e4-7f96-4423-85a2-ab0b98330431&width=768&dpr=4&quality=100&sign=3b13fcb&sv=2) **Vídeo** introducción a Flutter _(24 mins)_[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion#video-introduccion-a-flutter-24-mins) [https://www.youtube.com/watch?v=-pWSQYpkkjk](https://www.youtube.com/watch?v=-pWSQYpkkjk) * Características de Flutter. * Instalación y configuración de Flutter. * Plugin de Flutter. * Primera app Flutter en Android Studio. Hot Reload. * Widgets: ejemplo añadir un botón a la pantalla. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion#undefined) [PreviousReferencias y Recursos](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos) [NextPlataformas](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/plataformas) Last updated 11 months ago --- # Referencias y Recursos | 1. Introducción a Flutter ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#links-basicos) **Links básicos** * **Web oficial de** **Flutter** (English): [https://flutter.dev](https://flutter.dev/) * Web en **español** (no está tan actualizada): [https://esflutter.dev](https://esflutter.dev/) * **Flutter en el DartPad**: [https://dart.dev](https://dart.dev/) (seleccionar `New Pad--> Flutter`) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#flutter-api) Flutter API [https://api.flutter.dev/index.html](https://api.flutter.dev/index.html) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#instalacion-flutter-sdk) **Instalación Flutter SDK** [https://docs.flutter.dev/get-started/install](https://docs.flutter.dev/get-started/install) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#flutter-command-line-tool) Flutter command-line tool [https://docs.flutter.dev/reference/flutter-cli](https://docs.flutter.dev/reference/flutter-cli) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#entornos-de-desarrollo) **Entornos de Desarrollo:** * **Android Studio/IntelliJ**: [https://docs.flutter.dev/development/tools/android-studio](https://docs.flutter.dev/development/tools/android-studio) * **Visual Studio Code (VSCode)**: [https://docs.flutter.dev/development/tools/vs-code](https://docs.flutter.dev/development/tools/vs-code) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#quien-es-dash) ¿Quién es Dash? [https://docs.flutter.dev/dash](https://docs.flutter.dev/dash) ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F7fFsvuvqG0usIoC4j88M%252Fimage.png%3Falt%3Dmedia%26token%3D4b28fe7a-a383-4a6b-bd0a-d3eef0a908a2&width=768&dpr=4&quality=100&sign=acba9f15&sv=2) Dash (hummingbird) colibrí, mascota de Flutter y Dart ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#must-read-guide-why-flutter) Must read guide: _Why Flutter?_ [https://www.goodfirms.co/blog/must-read-guide-flutter-2022](https://www.goodfirms.co/blog/must-read-guide-flutter-2022) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#faqs) **FAQs** [https://flutter.dev/docs/resources/faq](https://flutter.dev/docs/resources/faq) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#flutter-versions-whats-new) Flutter versions: What's new? [https://docs.flutter.dev/whats-new](https://docs.flutter.dev/whats-new) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#guias-simples-how-to) Guías simples: How to....? [https://flutterguide.com](https://flutterguide.com/) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#mas) Más: [VsCode icons](https://github.com/microsoft/vscode-icons) [Flutter Gallery demonstrating the basic widgets](https://github.com/flutter/flutter/tree/master/examples/flutter_gallery) [Responsive design with Flutter](https://medium.com/flutter-community/developing-for-multiple-screen-sizes-and-orientations-in-flutter-fragments-in-flutter-a4c51b849434) [Awesome Flutter](https://github.com/Solido/awesome-flutter) [Flutter examples](https://github.com/flutter/flutter/tree/master/examples) [Youtube video about building reactive applications with Flutter](https://www.youtube.com/watch?v=RS36gBEp8OI&t=502s) [Charts for Flutter](https://medium.com/flutter/beautiful-animated-charts-for-flutter-164940780b8c) [Flutter architecture samples](https://github.com/brianegan/flutter_architecture_samples) [How rendering works in Flutter](https://medium.com/flutter-community/flutter-what-are-widgets-renderobjects-and-elements-630a57d05208) [Flutter and extension methods](https://quickbirdstudios.com/blog/dart-extension-methods/) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#advanced-articles) **Advanced Articles** * **Why is Flutter fast? (Widget-Element-Render Tree....)** [https://medium.com/flutter-community/why-is-flutter-fast-part-1-sublinear-building-317572cd6b47](https://medium.com/flutter-community/why-is-flutter-fast-part-1-sublinear-building-317572cd6b47) * **How Flutter renders contents to screen?** [https://tealfeed.com/flutter-basics-flutter-renders-contents-screen-a8544?utm\_source=pocket\_saves](https://tealfeed.com/flutter-basics-flutter-renders-contents-screen-a8544?utm_source=pocket_saves) * **Flutter Architecture:** * High level diagrams: [https://docs.google.com/presentation/d/1cw7A4HbvM\_Abv320rVgPVGiUP2msVs7tfGbkgdrTy0I/edit#slide=id.p](https://docs.google.com/presentation/d/1cw7A4HbvM_Abv320rVgPVGiUP2msVs7tfGbkgdrTy0I/edit#slide=id.p) * Detailed description: [https://flutter.dev/docs/resources/architectural-overview](https://flutter.dev/docs/resources/architectural-overview) #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/referencias-y-recursos#undefined) [PreviousObjetivos](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter) [Next1\. Introducción](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion) Last updated 1 year ago --- # Plataformas | 1. Introducción a Flutter Inicialmente Flutter sólo soportaba **Android** y **iOS** pero actualmente incluye soporte para **web**, **escritorio** (Windows, Mac, Linux), incluido **Fuchsia**. ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FpPjdpWLl0tZoXQjObvSv%252Fimage.png%3Falt%3Dmedia%26token%3D35cc2ee2-3c68-4aa0-a1b1-938bbb4e39dd&width=768&dpr=4&quality=100&sign=7b10239b&sv=2) Lista de **plataformas** **soportadas** por Flutter: [https://docs.flutter.dev/development/tools/sdk/release-notes/supported-platforms#supported-platforms](https://docs.flutter.dev/development/tools/sdk/release-notes/supported-platforms#supported-platforms) [Previous1\. Introducción](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion) [NextCasos de uso](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/casos-de-uso) Last updated 1 year ago --- # Paquetes y bibliotecas | 1. Introducción a Flutter El **repositorio** **oficial** de **paquetes** para Dart y Flutter lo tenemos disponible en: [![Logo](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fpub.dev%2Ffavicon.ico%3Fhash%3Dnk4nss8c7444fg0chird9erqef2vkhb8&width=20&dpr=4&quality=100&sign=6ca30c6d&sv=2)The official repository for Dart and Flutter packages.Dart packages](https://pub.dev/) En Flutter, `_**pub**_` es el sistema de **gestión** de **paquetes** de Dart. Se utiliza para administrar las dependencias de Dart y Flutter. Las **herramientas** **de** **Flutter** utilizan `_**pub**_` para leer el **fichero** `_pubspec.yaml_`, donde se **especifican** las **librerias** utilizadas por la aplicación, _**pub**_ las **descarga** y se **actualiza** la aplicación. [PreviousCaracterísticas destacables de Flutter](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/caracteristicas-destacables-de-flutter) [Next2\. Instalación del Flutter SDK](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk) Last updated 1 year ago --- # Casos de uso | 1. Introducción a Flutter La propia Google, Alibaba, Toyota, ...... Más ejemplos: [https://flutter.dev/showcase](https://flutter.dev/showcase) ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FssQRijJh4anYQWUBv3VQ%252Fimage.png%3Falt%3Dmedia%26token%3D205ec3e1-0205-4a5b-821b-56ccd23ce381&width=768&dpr=4&quality=100&sign=4b235c01&sv=2) Companies using Flutter ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F4SZFjeg7J71C46iVJdzq%252Fimage.png%3Falt%3Dmedia%26token%3Dead1b467-fa6c-4dc8-850e-960567a9fc33&width=768&dpr=4&quality=100&sign=45148554&sv=2) Apps developed with Flutter [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/casos-de-uso#demos) **Demos**: -------------------------------------------------------------------------------------------------------------------- ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F5r6MErT8p7URYa4ks24o%252Fimage.png%3Falt%3Dmedia%26token%3D06d32616-b320-423c-b929-40c9b3fce472&width=300&dpr=4&quality=100&sign=fb134409&sv=2) Juego 2D Pinball: [https://pinball.flutter.dev](https://pinball.flutter.dev/#/) [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/casos-de-uso#flutter-no-sera-tan-adecuado) **Flutter no será tan adecuado**: ------------------------------------------------------------------------------------------------------------------------------------------------------------------ * En **juegos** **2D**/**3D** **complejos**: mejor hacer uso de motores de juegos como Unity o Unreal. * En aplicaciones con **necesidades** **nativas** **específicas**: Si la aplicación sólo se va a ejecutar en una sola plataforma o requiere una **alta** **integración** con las características del dispositivo y las SDK de la plataforma, mejor desarrollar con las herramientas específicas de la plataforma. [PreviousPlataformas](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/plataformas) [Next¿Cómo funciona Flutter?](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/como-funciona-flutter) Last updated 1 year ago --- # ¿Cómo funciona Flutter? | 1. Introducción a Flutter Una **aplicación** **Flutter** se **ejecuta** de forma **nativa** en cada plataforma, gracias a la **compilación** Ahead Of Time (**AOT**). Flutter se comporta de forma similar a como lo hace un motor de videojuegos: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FzEvLI5BcEfT6TX0PFsyy%252Fimage.png%3Falt%3Dmedia%26token%3D3249c206-516a-44ce-8236-730df243bb4d&width=768&dpr=4&quality=100&sign=89a6c6b8&sv=2) * **Renderizando** elementos gráficos en un **canvas** de Skia (motor gráfico 2D de código abierto de Google que se usa también en: Google Chrome, Android, Chrome Os, Mozilla Firefox, ...) y enviándolo a la plataforma nativa. * La **plataforma** muestra el **canvas** y envía **eventos** a la aplicación en caso de necesitarlo (eventos de ciclo de vida, eventos de cambios de configuración, ...etc. ). Artículo: [https://buildflutter.com/how-flutter-works/](https://buildflutter.com/how-flutter-works/) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/como-funciona-flutter#flutter-vs-react-native) Flutter vs React Native Flutter, reactivo y declarativo, se parece a React Native, en cambio, **no necesita** ningún **puente Javascript,** por tanto, **las aplicaciones Flutter arrancan más rápido** y tienen **mejor** **rendimiento** (gracias a la compilación **AOT**) ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FHoJfpBpDlhBVVLITckht%252Fimage.png%3Falt%3Dmedia%26token%3D7a391b75-06fd-438b-b6ff-3e3ee714b522&width=768&dpr=4&quality=100&sign=35c75b52&sv=2) Flutter vs React Native A diferencia de React Native, todo en Flutter gira entorno a los **widgets** (**no se depende de los UI propios de cada plataforma: Flutter** pide una **ventana** al sistema operativo en el que se está ejecutando y **gestiona** **todo** el contenido **en** **Skia,** utilizando Dart. [PreviousCasos de uso](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/casos-de-uso) [NextCaracterísticas destacables de Flutter](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/caracteristicas-destacables-de-flutter) Last updated 11 months ago --- # Características destacables de Flutter | 1. Introducción a Flutter Flutter transformará el proceso de **desarrollo** y nos permitirá obtener, a partir del **mismo** **código base**, **aplicaciones** **multiplataforma,** **nativas**, **rápidas** y con interfaces de usuario muy **chulas.** * Flutter es de **código** **abierto**: puedes ver su evolución, crear tus propios parches, paquetes y contribuir a su desarrollo. * Flutter dispone de una **excelente** **documentación**. * Flutter **no** **es** un **lenguaje** de **programación**, es un **framework** de Dart. * Flutter está **escrito** **C**, **C++** y **Dart.** * Las **aplicaciones** **Flutter** se programan con **Dart**. Comparte muchas características de otros lenguages modernos como Kotlin y Swift. Además, Dart **traspila** a **Javascript**. * La **sintaxis** **declarativa** de Flutter para **crear** **interfaces** **de usuario** (utilizando Dart) le permite evitar el código repetitivo (boilerplate code) y ser extremadamente **productivos**. **Paradigmas** que usa Flutter: [https://esflutter.dev/docs/resources/faq#qué-paradigma-de-programación-usa-el-framework-de-flutter](https://esflutter.dev/docs/resources/faq#qu%C3%A9-paradigma-de-programaci%C3%B3n-usa-el-framework-de-flutter) * Durante el **desarrollo** de la aplicación, se permite su **recarga** en **caliente** (**hot** **reload**, compilación JIT): las actualizaciones en el código se aplican sin tener que volver a cargar el estado o recompilar la aplicación _\--> los cambios realizados se observan de forma instantánea en la aplicación en ejecución (sin perder el estado actual)._ * La **interfaz** de **usuario** de Flutter es **completamente** **personalizable** (UI customizable). En Flutter prácticamente todo es un **widget**, incluso la propia aplicación es un widget. (widgets para Google Material Design o iOS Cupertino listos para usar (out of the box). Podremos **crear** nuestros propios **widgets**. * Flutter proporciona excelentes **animaciones** y transiciones. * Para aquellas **funciones** **específicas** de la plataforma que aún no tienen un paquete de soporte de Flutter: Flutter admite la **interoperabilidad** de **C y C++**, así como canales de plataforma (**platform** **channels**) para interactuar con Kotlin/Java en **Android** y Swift/Objective-C en **iOS**. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/caracteristicas-destacables-de-flutter#arquitectura-de-flutter) Arquitectura de Flutter Flutter está organizado en **capas** de bibliotecas (libraries) **independientes**, lo cual las hace extensibles (y también reemplazables) donde cada capa depende de la capa inferior. ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FWuvZsbnIg2BMvYg4J2va%252Fimage.png%3Falt%3Dmedia%26token%3D59845a20-f486-40f7-b0d2-8b725846714c&width=768&dpr=4&quality=100&sign=337eb773&sv=2) Arquitectura de Flutter * **Framework**: programado únicamente en Dart, contiene las bibliotecas con todas las clases necesarias para widgets, rendering, animaciones, gestos, etc. Es la capa con la que el **desarrollador** **Flutter** **interactuará** habitualmente. * **Engine**: Fundamentalmente programado en C/C++. Proporciona todas las primitivas de bajo nivel para que las aplicaciones Flutter funcionen: **rendering** (**Skia**), **Dart** **runtime**, **channels**, etc. * **Embedder**: Todas las aplicaciones Flutter se **empaquetan** igual que otra **aplicación** **nativa**. Hay un embedder específico para cada plataforma. Flutter incluye embedders para las plataformas más comunes. Cada embedder se programa con el lenguaje que es adecuado para la plataforma, por ejemplo: Java and C++ para Android, Objective-C/Objective-C++ para iOS y macOS, any C++ for Windows and Linux. **Anatomia de las aplicaciones Flutter** ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FrfQCX8IkvUMGnMJKSCu5%252Fimage.png%3Falt%3Dmedia%26token%3De51363d7-0bc2-4702-97c1-d26f66d3b7c5&width=768&dpr=4&quality=100&sign=f9361bed&sv=2) Encontraremos toda la **información oficial** **sobre** la **arquitectura** en el siguiente enlace: [https://docs.flutter.dev/resources/architectural-overview](https://docs.flutter.dev/resources/architectural-overview) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/caracteristicas-destacables-de-flutter#undefined) [Previous¿Cómo funciona Flutter?](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/como-funciona-flutter) [NextPaquetes y bibliotecas](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/paquetes-y-bibliotecas) Last updated 1 year ago --- # 2. Instalación del Flutter SDK | 1. Introducción a Flutter Para desarrollar aplicaciones Flutter necesitamos **descargar** el Flutter SDK y configurarlo, para ello, tenemos 2 opciones: * Instalación rápida (**recomendada**) * Instalación manual Para instalarlo y configurarlo, sigue las instrucciones en las siguientes secciones. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk#que-incluye-el-flutter-sdk) ¿Qué incluye el Flutter SDK? El Flutter SDK **contiene** todos los _**paquetes**_ y _**herramientas**_ **de línea de comandos** que necesitamos para desarrollar aplicaciones Flutter para las diferentes plataformas: * [Dart SDK](https://dart.dev/tools/sdk) * Motor de **renderizado** optimizado para dispositivos móviles con excelente soporte para texto. * Framework **reactivo**. * Nutrido conjunto de **widgets** con el estilo Material Design y iOS (Cupertino) * APIs para **tests** unitarios y de integración. * Plugins para interactuar con la plataforma así como APIs de terceros. * [Dart DevTools](https://docs.flutter.dev/development/tools/devtools) para testear, depurar y ver el rendimiento (profiling) de la aplicación. * **Comandos**: `flutter` y `dart` para crear, compilar y testear desde el terminal. [PreviousPaquetes y bibliotecas](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/1.-introduccion/paquetes-y-bibliotecas) [NextInstalación rápida](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-rapida) Last updated 9 days ago --- # Instalación rápida | 1. Introducción a Flutter La forma más **simple** de **descargar, configurar** y **probar** el SDK de Flutter en nuestro sistema es realizarlo a través de **Visual Studio Code**. Luego, **completaremos** la **configuración** para el desarrollo de aplicaciones **Android** con Flutter. Para ello, realizaremos las siguientes **2** **acciones** contenidas en las secciones desplegables: 1\. Descarga y configuración inicial de Flutter[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-rapida#id-1.-descarga-y-configuracion-inicial-de-flutter) Se ofrece solo un **resumen**, seguiremos las **instrucciones** de la **documentación** **oficial** para nuestro sistema operativo: [https://docs.flutter.dev/get-started/quick](https://docs.flutter.dev/get-started/quick) **Resumen** de los **pasos**: 1. **Software necesario:** git y Visual Studio Code, bibliotecas, etc. (si no los tenemos en el sistema, instalarlos) 2. **Instalación y configuración de Flutter:** Se realiza fácilmente a través Visual Studio Code: 1. Añadimos primero la extensión de Flutter. 2. Luego, creamos un nuevo proyecto Flutter, donde se detecta que no tenemos el Flutter SDK y comenzará a descargarlo en la carpeta contenedora que hayamos elegido (**se creará una nueva carpeta dentro de la carpeta contenedora**) 3. Por último, le indicamos que lo añada al PATH del sistema (para tenerlo accesible desde el terminal en cualquier directorio) 3. **Ejecución del proyecto Flutter creado:** Probamos la aplicación, que se ejecutará en Chrome (se abrirá automáticamente). 2\. Configuración para el desarrollo con Flutter para dispositivos Android.[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-rapida#id-2.-configuracion-para-el-desarrollo-con-flutter-para-dispositivos-android) Para ejecutar, compilar y desplegar las aplicaciones Flutter en dispositivos Android deberemos realizar una serie de configuraciones. **Deberemos** consultar la **documentación** **oficial** para más detalles: [https://docs.flutter.dev/platform-integration/android/setup](https://docs.flutter.dev/platform-integration/android/setup) **Resumen** de los **pasos**: 1. En **Android Studio** (ya instalado previamente)**:** 1. Realizar las siguientes comprobaciones/acciones en Tools -> SDK Manager (reiniciarlo si se han hecho cambios): 1. **SDK Platforms:** **API Level** **36** seleccionada. 2. **SDK Tools:** Han de estar seleccionados: * Android SDK Build-Tools * Android SDK Command-line Tools * Android Emulator * Android SDK Platform-Tools 2. Instalaremos el **Plugin Flutter** (que instala también el plugin Dart) para desarrollar aplicaciones Android con Flutter en Android Studio. 2. **Aceptar las licencias Android:** Antes de poder compilar una aplicación Flutter para Android **deberemos** leer y aceptar las licencias de la plataforma Android SDK. Para ello, ejecutaremos desde un terminal el comando: `$ flutter doctor --android-licenses` Una vez aceptadas, nos informará con el mensaje: `All SDK package licenses accepted` 1. Deberemos tener un AVD o un Dispositivo físico Android disponibles. 2. **Validar la configuración de Flutter:** Ejecutaremos los siguientes comandos, prestando atención a los possibles errores: 1. `$ flutter doctor` 2. `$ flutter emulators && flutter devices` Con todos los pasos anteriores ya podremos ejecutar, depurar y desplegar aplicaciones Flutter en dispositivos Android. El **desarrollo** lo podremos realizar desde Visual Studio Code o con Android Studio/IntelliJ (con el plugin de Flutter instalado). [Previous2\. Instalación del Flutter SDK](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk) [NextInstalación manual](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual) Last updated 9 days ago --- # Instalación manual | 1. Introducción a Flutter Realizar los siguientes pasos: 1 #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual#descargar-flutter-sdk) Descargar Flutter SDK **Paso A. Descargar el Flutter SDK bundle** adecuado para nuestro sistema operativo de desarrollo: [https://docs.flutter.dev/get-started/install](https://docs.flutter.dev/get-started/install) > El SDK de Flutter incluye también Dart SDK, por tanto, no hay que descargarlo por separado. ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FlEMicdfd95feLpDDv3ua%252Fimage.png%3Falt%3Dmedia%26token%3Db607d048-f237-428f-9e99-b54797ea0790&width=768&dpr=4&quality=100&sign=bce6ca79&sv=2) > Además, para el **desarrollo de aplicaciones** **móviles**, necesitaremos > > * **Android** **SDK** si vamos a desarrollar aplicaciones **Android**. Lo más cómodo es instalarlo junto con Android Studio: [https://developer.android.com/studio](https://developer.android.com/studio) > > * **XCode** para desarrollar aplicaciones **iOS**: [https://flutter.dev/docs/get-started/install/macos#install-xcode](https://flutter.dev/docs/get-started/install/macos#install-xcode) > **Paso B. Descomprimir** el bundle del **Flutter SDK** en el lugar deseado. **Atención en Windows:** Tener en cuenta que sea una carpeta **accesible** por el usuario, con **privilegios** suficientes, **y que no incluya espacios en la ruta ni en el nombre**. 2 #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual#anadir-flutter-al-path-del-sistema) **Añadir** _**flutter**_ **al** _**path**_ **del sistema** Para tener disponible la **herramienta** de línea de comandos `**flutter**` desde cualquier directorio del sistema, la añadiremos al **PATH** según instrucciones de instalación para nuestro sistema operativo: [https://docs.flutter.dev/get-started/install/linux#update-your-path](https://docs.flutter.dev/get-started/install/linux#update-your-path) * Por ejemplo, en Linux, para el usuario actual, lo añadiremos al final de alguno de los siguientes ficheros: ~/`.bashrc` (que ya existe) o `~/.bash_profile`, o `~/.bash_login`, `~/.profile` (si no existe el fichero, lo creamos). Otra alternativa, es añadirlo a `/etc/profile` (para que se aplique en todos los usuarios) 3 #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual#comprobar-la-instalacion) **Comprobar** la **instalación** Una vez instalado Flutter, desde un **Terminal**, **ejecutaremos** el comando: `**flutter doctor -v**` que nos informará cualquier problema que se detecte en la instalación de Flutter. **Atención si vamos a desarrollar para Android:** Flutter necesita las herramientas de línea de comandos: `**Android SDK Command-Line Tools**` (las podemos instalar manualmente o desde el **Android Studio SDK Manager**) * `flutter doctor` nos **advierte** de que las **Android Licenses no han sido aceptadas**. Hay que **aceptarlas**, por tanto, ejecutaremos el comando que se nos indica: `flutter doctor --android-licenses` ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FfcR9IiIdy0TMiF4q9W6P%252Fimage.png%3Falt%3Dmedia%26token%3D8756d752-d2dd-43eb-a030-6efbb12393cf&width=768&dpr=4&quality=100&sign=89ae2fe5&sv=2) * Si es necesario, instalaremos también otras **dependencias** que nos falten (consultar al final de este documento el apartado: "Atencion usuarios Linux / Mac") Si `flutter doctor` muestra una **ruta** **incorrecta** para el **Android SDK**, (por ejemplo, nos muestra /usr/lib/android-sdk y lo tenemos instalado en otra ruta) se **configurará** **manualmente ejecutando**: `flutter config --android-sdk ` 4 #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual#instalar-plugin-de-flutter-para-android-studio) Instalar plugin de Flutter para Android Studio Abrimos Android Studio y le añadimos el **plugin** de **Flutter** y **Dart**: [https://flutter.dev/docs/get-started/editor](https://flutter.dev/docs/get-started/editor) > Se puede desarrollar aplicaciones Flutter en un simple editor de texto y la línea de comandos. Se recomienda utilizar un IDE: Visual Studio Code (rápido, estable y ligero) o Android Studio/IntelliJ **Atención**: puede que si ejecutamos `flutter doctor -v` no se reconozcan los plugins instalados en una versión del IDE más reciente. No hay que preocuparse, los plugins funcionarán perfectamente. ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F5VPHIaDnJqWd0lHY1lT2%252Fimage.png%3Falt%3Dmedia%26token%3D18facec6-bdea-4d8d-8be3-dd2ddce534dd&width=300&dpr=4&quality=100&sign=c0c1d30a&sv=2) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual#atencion-usuarios-de-linux-mac) Atención usuarios de Linux/Mac Atención usuarios Linux[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual#atencion-usuarios-linux) Si en Linux (Ubuntu, Fedora, Arch, etc.), vemos el siguiente mensaje**:** ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FGQ54p1JLleqdBccHW97Q%252Fimage.png%3Falt%3Dmedia%26token%3D7971d814-98ba-4227-9053-89461a7b5a17&width=300&dpr=4&quality=100&sign=c74fcd2b&sv=2) Tendremos que **instalar** **paquetes** adicionales. * For **Ubuntu**: `sudo apt-get install lib32stdc++6` * For Fedora: `dnf install libstdc++.i686` * For Arch: `pacman -S lib32-libstdc++5` along with the instructions on this link: [https://wiki.archlinux.org/index.php/Official\_repositories#multilib](https://wiki.archlinux.org/index.php/Official_repositories#multilib) Atención usuarios Mac[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual#atencion-usuarios-mac) Si ejecutamos `flutter doctor -v` y observamos un mensaje similar al siguiente: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FqAVPj5Ja9188LOtXzTvF%252Fimage.png%3Falt%3Dmedia%26token%3Deb5e9206-4f35-4235-967b-f499530f78e2&width=300&dpr=4&quality=100&sign=c8af124d&sv=2) \-> Hay un problema con el nombre del directorio, ejecutamos los comandos: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FKy1iQzd7zt1WTf2q9aK8%252Fimage.png%3Falt%3Dmedia%26token%3Dd0ace96a-5706-42df-8c63-1a319d759294&width=300&dpr=4&quality=100&sign=b1766cc6&sv=2) \-> Ejecutamos de nuevo `flutter doctor -v` para comprobar que se ha solucionado. [PreviousInstalación rápida](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-rapida) [NextEjemplo, Flutter in Ubuntu: Step by Step.](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual/ejemplo-flutter-in-ubuntu-step-by-step.) Last updated 9 days ago --- # Ejemplo, Flutter in Ubuntu: Step by Step. | 1. Introducción a Flutter ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fmedia.geeksforgeeks.org%2Fwp-content%2Fuploads%2F20200823110811%2Ff1-300x300.png&width=768&dpr=4&quality=100&sign=a458bbc6&sv=2) > We will be setting up flutter in **VS Code** since it allows a much smoother performance on almost any system (even if your system is having 4GB of Ram or low), overall time taken for various tasks reduced nearly by 75% when compared to the time taken while using Android Studio. The process involved in the setting up process are : #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual/ejemplo-flutter-in-ubuntu-step-by-step.#id-1-downloading-vs-code) 1) Downloading VS Code * VS Code or Visual Studio Code is an amazing all-in-one code editor developed by the team at Microsoft. It is **free** and **open**\-**sourced**. * You can **download** VS Code: * From [here](https://code.visualstudio.com/) . It doesn’t have much download size and is easy to set up. * You can also use the terminal to install the VS Code on your system, by running the following code : `$ sudo apt install code` #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual/ejemplo-flutter-in-ubuntu-step-by-step.#id-2-downloading-flutter-sdk) **2) Downloading Flutter SDK** After installing VS Code, we need to **install Flutter SDK** so that it will enable VS Code to build flutter applications. In order to install the flutter SDK, you have to follow instructions from the [Flutter Website](https://flutter.dev/docs/get-started/install/linux) Once you’re done installing the VS Code and Flutter SDK, let’s try opening VS Code. If there hadn’t been any installation errors, VS Code will open without any issue. After loading up, we need to **enable** **Git** which is a version control system (VCS) which will be really helpful in the later stages. For this, select VCS Option from the left side of the VS Code. Please refer to the below image if you’re new to VS Code. ![VCS option](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fmedia.geeksforgeeks.org%2Fwp-content%2Fuploads%2F20200823113253%2Fs2-660x436.png&width=300&dpr=4&quality=100&sign=ba4f3796&sv=2) After selecting that, you will find an option to install Git. Once you click on that, you will be taken to the website from which you can download Git for your system. You can also install Git by running the following code on your terminal. Copy $ sudo apt update $ sudo apt install git After Installing Git, come back to the VS Code and select the **Extensions** (the icon present at two down the position with that of VCS). ![installing git](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fmedia.geeksforgeeks.org%2Fwp-content%2Fuploads%2F20200823114235%2Fs34-660x436.png&width=300&dpr=4&quality=100&sign=5fcaf432&sv=2) From that, you have to **search** **for** **flutter** **and** **install** that extension. Also, **make sure that Dart is also installed i**n the same method. ![flutter plugin](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fmedia.geeksforgeeks.org%2Fwp-content%2Fuploads%2F20200823114314%2Fs341-660x436.png&width=300&dpr=4&quality=100&sign=aca6daf7&sv=2) Now you’re nearly ready to go. There is one more final installation that you need to perform before you’re all set to go. You will have to install Android Studio for all the essential packages like Manager or if you need to add any virtual devices via AVD Manager. #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual/ejemplo-flutter-in-ubuntu-step-by-step.#id-4-installing-android-studio) **4) Installing Android Studio** Though we might be able to download all the packages separately, it may lead on to some errors. To avoid that, let’s install Android Studio so that all the essential packages will get added correctly. You can install Android Studio by running the following command on the terminal. * First **install** **JDK** : Copy $ sudo apt install openjdk-17-jdk * Now, you can **install** **Android** **Studio from** [https://developer.android.com/studio/install](https://developer.android.com/studio/install) or: Copy $ sudo snap install android-studio --classic After installing Android Studio, open it from the Applications directory and run it. You will be asked whether to import any settings and select ‘Do not import’ for that. Move ahead with the installation flow and finally, all the installation will be over. After the installation is over, you will reach the **starting** **page**. From there select the ‘**Configure**’ option present on the right side bottom. ![configure android studio](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fmedia.geeksforgeeks.org%2Fwp-content%2Fuploads%2F20200823120640%2Fs56-660x436.png&width=300&dpr=4&quality=100&sign=b86908ed&sv=2) Now, you have to **select** ‘**SDK** **Manager**’ from the list and you will be redirected to a page where you can install the required Android SDKs for various Android OS Versions. **Please make sure that you’re installing the SDK of the same version as that of your phone or the virtual device which you will be setting up later**. Select them and **click** on ‘**Apply**’. After that, you will be prompted to install them and follow the procedure. ![select android version](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fmedia.geeksforgeeks.org%2Fwp-content%2Fuploads%2F20200823121015%2Fs561-660x436.png&width=300&dpr=4&quality=100&sign=7fc2a9ed&sv=2) Once everything is complete, **close** **everything** including **Android** **Studio** as well as **VS** **Code**. You can **restart VS Code now.** Within VS Code, you can create a new workspace folder (where your project files will be stored). After that, click on View from the top Tool Bar and select the Command Panel. ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fmedia.geeksforgeeks.org%2Fwp-content%2Fuploads%2F20200823122614%2Fs563-660x436.png&width=768&dpr=4&quality=100&sign=64845451&sv=2) In that type in Flutter New Project and select it. If everything has been set up correctly, you will be asked to type in your project name. Sometimes, you will be asked to locate the Flutter SDK. In that case, provide the location where you installed the Flutter SDK. If there were no errors, a project of the name that you provided will load up in a moment. The same can also be achieved by running the following command on the terminal present on VS Code (select Terminal from the toolbar on the top and run the following command. `flutter create ` where can be changed with the name of your preference. Once the project loads completely, all the files can be accessed from the Files section of VS Code present on the left side tool bar (2 positions above that of the VCS). You may connect your physical device (android) for installing the application or you may install a new Android Virtual Device from the AVD Manager, just like how we installed the SDKs from SDK Manager. The Run option can be found just below VCS and it can be used to run and debug your application. Now, you’re all set to develop flutter application using VS Code. Happy Coding! [PreviousInstalación manual](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual) [Next3\. Primera aplicación en Flutter](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter) Last updated 9 days ago --- # 3. Primera aplicación en Flutter | 1. Introducción a Flutter Vamos a **crear** y **ejecutar** una aplicación Flutter desde una plantilla por defecto de diferentes formas utilizando alguna de las siguientes herramientas: * Los comandos de Terminal \* * Android Studio \* * Visual Studio Code \* * DartPad **\*** **Atención**: Requieren tener instalado el Flutter SDK [PreviousEjemplo, Flutter in Ubuntu: Step by Step.](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/2.-instalacion-del-flutter-sdk/instalacion-manual/ejemplo-flutter-in-ubuntu-step-by-step.) [NextDesde el Terminal](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-terminal) Last updated 9 days ago --- # Desde el DartPad | 1. Introducción a Flutter Podemos probar también Flutter en el navegador: * Accedemos a la web del DartPad: [https://dartpad.dev/?](https://dartpad.dev/?) * Pulsamos sobre `**New Pad**` y seleccionamos `**Flutter -> Create**` ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252Fsw24hsW6T4GKwSoiAtxq%252Fimage.png%3Falt%3Dmedia%26token%3D812e3b68-2767-4943-ab58-208ee181cc62&width=768&dpr=4&quality=100&sign=c4b47b2f&sv=2) Seleccionamos **Flutter** y **Create**. Ejecutamos la aplicación pulsando en `**Run**`**:** ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FdR8M50fnU8A58B4ricq3%252Fimage.png%3Falt%3Dmedia%26token%3D5a282438-74a7-4893-a111-6c79008d0c25&width=768&dpr=4&quality=100&sign=5efb1b96&sv=2) [PreviousDesde Visual Studio Code](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-visual-studio-code) [NextHot Reload - Hot Restart - Full Restart](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/hot-reload-hot-restart-full-restart) Last updated 3 years ago --- # Desde Android Studio | 1. Introducción a Flutter Toda la información y detalles: [https://docs.flutter.dev/get-started/test-drive?tab=androidstudio](https://docs.flutter.dev/get-started/test-drive?tab=androidstudio) **Atención**: Los _plugins_ de Dart y Flutter han de estar instalados y habilitados. [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-android-studio#creamos-un-nuevo-proyecto-flutter) Creamos un nuevo proyecto Flutter ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 1. Abrimos Android Studio y elegimos: `**Crear New Flutter Project**`: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F9odcTtauz6xod8SgsIRz%252Fimage.png%3Falt%3Dmedia%26token%3Dccef4f48-f9a9-41a7-8597-6eacbc8378a3&width=768&dpr=4&quality=100&sign=67fdb74c&sv=2) 2\. Escribimos el **nombre** del proyecto: _**helloflutter**_, (eligimos las opciones que se ven en la imagen y completamos con helloflutter la sección _More Settings_) 3\. Pulsamos `**Finish**` para crear el proyecto. ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FCVkotf6dOMfbBpslMyoK%252Fimage.png%3Falt%3Dmedia%26token%3D870b9f4b-1dd9-4a0e-aff8-1c7402683b6d&width=768&dpr=4&quality=100&sign=a27a8ccf&sv=2) 4\. El **proyecto** Flutter quedaría similar a la siguiente imagen (con el fichero _main.dart_ abierto en el editor): ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FegjQ8TgfbeldmdSCKmsI%252Fimage.png%3Falt%3Dmedia%26token%3D1101920d-3ca9-47e6-a86a-e24b65131143&width=768&dpr=4&quality=100&sign=d9fa22c3&sv=2) Si es necesario, configuramos Project Settings....[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-android-studio#si-es-necesario-configuramos-project-settings) En principio, los siguientes pasos no serían necesarios (solo si detectamos problemas al ejecutar o al editar el proyecto Android): 1. Abrimos Project Settings y cambiaremos al último SDK y versión de java compatible en **Project** y en **Modules:** ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F6UKQSboD8RxzGJsaZs31%252Fimage.png%3Falt%3Dmedia%26token%3D6510a714-476c-442e-81bc-8b59615a61b0&width=300&dpr=4&quality=100&sign=ab1fb1b7&sv=2) 1. Abrimos `**android/app/build.gradle**`: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F3Ujl6WodI95LotrJBtyT%252Fimage.png%3Falt%3Dmedia%26token%3D344770eb-46f1-4dff-9db1-4c4d3d805a88&width=300&dpr=4&quality=100&sign=dbcb59c0&sv=2) y sustituimos `_**GradleException**_` por _**FileNotFoundException**_: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FugQnkWidoXolbjhougpC%252Fimage.png%3Falt%3Dmedia%26token%3Da9ab98c9-7826-43f0-bce0-46e6e97bb033&width=300&dpr=4&quality=100&sign=a300d25e&sv=2) [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-android-studio#ejecutamos-la-aplicacion) **Ejecutamos la aplicación** ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * **Arrancamos** un AVD Android * **Ejecuta** la aplicación desde el menú o la barra de herramientas, que arrancará: lib/**main.dart** ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FbrV9vGgiMb1bTM1lnNo3%252Fimage.png%3Falt%3Dmedia%26token%3Dcd5a17f1-defe-4ea7-91b2-ca767ff9a1ec&width=768&dpr=4&quality=100&sign=ade3ef12&sv=2) ⚠️ **Gradle warnings**[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-android-studio#gradle-warnings) Si, al ejecutar, vemos en la ventana "Run" que gradle muestra mensajes de warning, es por la versión de gradle: la _actualizaremos_ en _build.gradle_ y en _gradle-wrapper.properties._ ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FEC9fWxdwcIPYPdAIEkxJ%252Fimage.png%3Falt%3Dmedia%26token%3Dde16b671-1e55-41c9-bb47-926b9b68f520&width=300&dpr=4&quality=100&sign=8eaee225&sv=2) ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F1jSNEWxShsgy9asiHUA4%252Fimage.png%3Falt%3Dmedia%26token%3D205f32f9-cf4f-48bb-8e4a-33a22f3b2554&width=768&dpr=4&quality=100&sign=3c841172&sv=2) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-android-studio#probamos-hot-reload) Probamos hot reload Cuando desarrollamos con Flutter, podemos utilizar ⚡ `**hot reload**` para reflejar de forma **instantánea** los cambios del código en la aplicación que se está ejecutando, sin necesidad de reiniciar la ejecución (y conservando el estado) Vamos a probarlo, **abrimos** _main.dart_ * **Cambiamos** el texto de la barra del título 'Flutter Demo Home Page' por _'__**HELLO FLUTTER**__'_ * Veremos los cambios en ejecución en el momento que **guardamos** el fichero o pulsamos el **icono** de `**Hot Reload**` (o si ponemos en primer plano el dispositivo) * Y vemos el **resultado** de inmediato en el dispositivo: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FW7eMQzuef3SALVeJuDhP%252Fimage.png%3Falt%3Dmedia%26token%3D26de5dda-df35-42d8-b65f-18eb5a23ca0a&width=300&dpr=4&quality=100&sign=f47daaaa&sv=2) > **Atención**: Hot reload puede no siempre ser posible. En algunas ocasiones, se tendrá que hacer un _hot restart,_ o un _full restart_. Para más detalles, consultar la documentación: > > [https://docs.flutter.dev/development/tools/hot-reload](https://docs.flutter.dev/development/tools/hot-reload) [PreviousDesde el Terminal](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-terminal) [NextDesde Visual Studio Code](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-visual-studio-code) Last updated 9 days ago --- # 4. Conceptos fundamentales en Flutter | 1. Introducción a Flutter [Estructura de una Aplicación Flutter](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/estructura-de-una-aplicacion-flutter) [Widgets](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets) [Ciclo de Vida](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida) [PreviousHerramientas para debugging. Logs](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/herramientas-para-debugging.-logs) [NextEstructura de una Aplicación Flutter](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/estructura-de-una-aplicacion-flutter) Last updated 1 year ago --- # Hot Reload - Hot Restart - Full Restart | 1. Introducción a Flutter ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/hot-reload-hot-restart-full-restart#hot-reload) **Hot reload ⚡️** Carga los cambios del código en la VM o en el navegador y reconstruye el árbol de widgets, **preservando** el **estado** **de la aplicación**; **pero NO ejecuta de nuevo** `**main()**` **o** `**initState()**`**.** (`⌘\` o `CTRL\` en Intellij and Android Studio, `⌃F5` en VSCode) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/hot-reload-hot-restart-full-restart#hot-restart) **Hot restart** 🔄 Carga los cambios del código en la VM o en el navegador, y **reinicia** la **aplicación**, por tanto, **se** **pierde** **el** **estado** **de la aplicación**. En el navegador, permite reiniciar la aplicación sin tener que recargar la página. (`⇧⌘\` o `⇧CTRL\` en IntelliJ and Android Studio, `⇧⌘F5` en VSCode) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/hot-reload-hot-restart-full-restart#full-restart) **Full restart** ⏹️ * **Reinicia por completo** la **aplicación** iOS, Android, o web. Esta operación es lenta pues **recompila** **de nuevo** el código Java / Kotlin / Objective-C / Swift. En la web, también reinicia el Dart Development Compiler. (No hay un atajo de teclado, se debe parar y volver ejecutar la aplicación) * Ocurre **siempre** que **paramos** la aplicación y la **ejecutamos** de nuevo. Más información en: [https://docs.flutter.dev/tools/hot-reload](https://docs.flutter.dev/tools/hot-reload) [PreviousDesde el DartPad](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-dartpad) [NextHerramientas para debugging. Logs](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/herramientas-para-debugging.-logs) Last updated 9 days ago --- # Desde el Terminal | 1. Introducción a Flutter Información oficial: [https://flutter.dev/docs/get-started/test-drive?tab=terminal](https://flutter.dev/docs/get-started/test-drive?tab=terminal) [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-terminal#creamos-un-proyecto-flutter) **Creamos un proyecto Flutter** ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1. **Abrimos** una ventana de comandos (**terminal**): 2. **Creamos** un nuevo proyecto llamado `_**myfirstapp**_` (creará el proyecto dentro del directorio `_**myfirstapp**_`: `flutter create myfirstapp` **Atención:** La aplicación se crea por **defecto** con el nombre de **package** _com.example, y_ los **lenguajes** _kotlin_ y Swift, podremos especificarlos de forma explícita ( o ) añadiendo los parámetros --org, -a (para android: Java/Kotlin) y -i (para ios: Swift/Objective-C). Ejemplo: `$ flutter create --org dam.empar -a kotlin -i swift myfirstapp` Para ver más información de los parámetros: `flutter create -h` **En un proyecto existente**, podremos **añadir** **plataformas desktop** deseadas (separándolas por **,** ) : `$ flutter create --platforms=windows,macos,linux .` Más info: [https://docs.flutter.dev/development/platform-integration/desktop#add-desktop-support-to-an-existing-flutter-app](https://docs.flutter.dev/development/platform-integration/desktop#add-desktop-support-to-an-existing-flutter-app) 3\. Para ver los **dispositivos** disponibles que tenemos en funcionamiento, ejecutaremos: `flutter devices` ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FcJg2UNJ3bd16W1Enunat%252Fimage.png%3Falt%3Dmedia%26token%3Df77bcabf-2f8d-4679-8ee8-d220a42f2528&width=768&dpr=4&quality=100&sign=7ed65abc&sv=2) 1. Para listar **AVDs (emuladores)** que tenemos disponibles, con su ID: `flutter emulators` 1. Para **arrancar** un dispositivo en el emulador por su ID: `flutter emulators --launch ` También, podemos arrancar el emulador desde el SDK Android para un AVD ya creado. Por ejemplo, para abrir un AVD llamado _Pixel\_XL\_API\_31_ ejecutamos: `$ ./emulator -avd Pixel_XL_API_31` [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-terminal#ejecutamos-la-aplicacion) Ejecutamos la aplicación --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Cambiamos al directorio del proyecto creado y ejecutamos: `flutter run -d ` Por defecto, si no identificamos el dispositivo pero ya tenemos uno conectado, se ejecutará en ese dispositivo o, si no hay ninguno, se ejecutará en el navegador Chrome. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-terminal#a.-ejecucion-en-android-avd) **A. Ejecución en Android** **AVD**: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FNY7tRxnjlKoNHttKTVa3%252Fimage.png%3Falt%3Dmedia%26token%3Ddf7a361f-f50e-4d20-97a7-84f30bb962f0&width=768&dpr=4&quality=100&sign=7e82f099&sv=2) ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252Fsufa6DzIbrng6W3RZr2K%252FFirstFlutterApp.gif%3Falt%3Dmedia%26token%3Ddf9165f0-1250-4ba6-bb04-ca46fffd143d&width=300&dpr=4&quality=100&sign=dd612971&sv=2) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-terminal#b.-ejecucion-en-chrome) **B. Ejecución en** **Chrome**: Cerramos/desconectamos los dispositivos y arrancamos de nuevo: `flutter run` o también `flutter run -d chrome` ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FBx7bOO30FJBHmOkxIHOk%252Fimage.png%3Falt%3Dmedia%26token%3D453f6243-6148-4c76-9f41-804e71012f03&width=768&dpr=4&quality=100&sign=71c2f347&sv=2) ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FN1cIUY69cdxMobhtKPYh%252Fimage.png%3Falt%3Dmedia%26token%3D3714c983-a1b4-41fa-926c-2acd8d60150f&width=768&dpr=4&quality=100&sign=48e356f5&sv=2) #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-terminal#probamos-hot-restart) Probamos Hot restart Durante la ejecución, si modificamos el código, y **pulsamos "R**" podremos realizar un **"hot restart"** que reiniciará la aplicación y mostrará los cambios (stop & run) #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-terminal#profiler-devtools) Profiler/DevTools Una vez arrancada la aplicación, podemos también **abrir** la **URL** proporcionada para ver el **Profile** o abrir la URL con las **DevTools** asociadas a la aplicación en ejecución: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F8Lk03CzAhheFKTxP2916%252Fimage.png%3Falt%3Dmedia%26token%3Dafe9603a-e3e1-45f2-9540-8fea3d0c5c79&width=768&dpr=4&quality=100&sign=19281bac&sv=2) ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FmMSwHDsByS5lkYDwUqjV%252Fimage.png%3Falt%3Dmedia%26token%3Dc21a35c4-a615-4470-a133-fd42dcf0c15e&width=768&dpr=4&quality=100&sign=35da8578&sv=2) [Previous3\. Primera aplicación en Flutter](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter) [NextDesde Android Studio](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-android-studio) Last updated 10 months ago --- # Widgets | 1. Introducción a Flutter Catálogo de widgets: [https://docs.flutter.dev/development/ui/widgets](https://docs.flutter.dev/development/ui/widgets) Para practicar: [https://docs.flutter.dev/development/ui/interactive](https://docs.flutter.dev/development/ui/interactive) En Flutter los elementos de la UI son objetos del tipo **Widget** (casi todo en una aplicación Flutter son widgets) El **widget** describe cómo debe mostrarse el elemento UI en pantalla teniendo en cuenta la actual **configuración** y el **estado**. Flutter proporciona un **catálogo** muy completo de **widgets** **standard** de todo tipo: botones, listas, pilas, .... Los widgets se pueden **personalizar** utilizando las propiedades y pueden contener uno o más hijos. Así, por ejemplo, si queremos un widget que muestre un texto personalizado, crearemos un nuevo widget que se **componga** de Text. * Flutter prefiere la **composición** sobre la herencia. Toda app Flutter se compone de ventanas que a su vez se componen de widgets: **app -> screens -> widgets** Los widgets están diseñados para ser **inmutables** (unchangeable) lo que ayuda a mantener la UI muy ligera (para actualizar la UI se deberá crear una nueva instancia con los cambios: Flutter se encarga de reutilizar y recyclar de forma eficiente los widgets) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets#tipos-de-widgets) Tipos de Widgets Nuestras aplicaciones se comprondrán de widgets que son **subclase** de: * `**StatelessWidget**`: Widgets que solo dependen para su configuración de la información **estática** que contienen (por ejemplo, una imagen estática en un image view, o un texto de título). * `**StatefulWidget**`: Widgets que necesitan mantener información de **estado** dinámica. Lo consiguen utilizando un objeto del tipo `State`. Ambos tipos de **widgets**, `stateless` y `stateful` **se redibujan cada vez que el framework de Flutter se lo pide, por tanto,** **todo widget deberá implementar el método** `**build()**` (que describe el widget a partir de otros widgets, configurando así el **árbol de widgets**) La **diferencia** entre ambos tipos de widgets es que los widgets `**stateful**` delegan su configuración a un objeto `**State**` y se pueden **actualizar** a **petición** en tiempo de ejecución. [PreviousEstructura de una Aplicación Flutter](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/estructura-de-una-aplicacion-flutter) [NextStateless widget](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateless-widget) Last updated 11 months ago --- # 6. Tips & Tricks | 1. Introducción a Flutter ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/6.-tips-and-tricks#visual-studio-code-shorcuts-extensions-settings) **Visual Studio Code: shorcuts/extensions/settings** [https://codewithandrea.com/articles/vscode-shortcuts-extensions-settings-flutter-development/](https://codewithandrea.com/articles/vscode-shortcuts-extensions-settings-flutter-development/) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/6.-tips-and-tricks#android-studio-como-mostrar-la-herramienta-database-inspector) Android Studio: Cómo mostrar la herramienta Database Inspector? `View` > `Tool Windows` > `App inspection` ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/6.-tips-and-tricks#ides-mostrar-las-lineas-guia-en-el-codigo) **IDEs: Mostrar las líneas guía en el código** (show UI guidelines for methods) * **Android Studio**: check `Show UI guides for build methods` [![image](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fuser-images.githubusercontent.com%2F52930304%2F131476424-345da076-5b13-4fab-9f7a-385b9aef8372.png&width=300&dpr=4&quality=100&sign=30e0ad08&sv=2)](https://user-images.githubusercontent.com/52930304/131476424-345da076-5b13-4fab-9f7a-385b9aef8372.png) **Atención**: Debido a un bug en el plugin, si escogemos lenguaje **Java** al crear el proyecto Flutter, **no se visualizan las UI guidelines**, aunque las activemos_._ En Visual Studio Code sí se visualizan siempre. * **En Visual Studio Code:** Hay que marcar en la configuración: `Preview Flutter UI Guides` [![image](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fuser-images.githubusercontent.com%2F52930304%2F131477575-4448191c-f43e-4ece-ac74-7a6fac54fd38.png&width=300&dpr=4&quality=100&sign=b2fa7d4&sv=2)](https://user-images.githubusercontent.com/52930304/131477575-4448191c-f43e-4ece-ac74-7a6fac54fd38.png) [Previous5\. Recomendaciones (best practices)](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices) Last updated 2 years ago --- # Herramientas para debugging. Logs | 1. Introducción a Flutter Más información en: [https://docs.flutter.dev/testing/code-debugging](https://docs.flutter.dev/testing/code-debugging) Para realizar **debugging** de las aplicaciones Flutter tenemos variedad de herramientas: * [DevTools](https://docs.flutter.dev/development/tools/devtools) , suite de herramientas de rendimiento y profiling disponibles **desde** el **navegador**. * [Android Studio/IntelliJ](https://docs.flutter.dev/development/tools/android-studio#run-app-with-breakpoints) , y [VS Code](https://docs.flutter.dev/development/tools/vs-code#run-app-with-breakpoints) (con los plugins de Flutter y Dart ) permiten depuración del código con _breakpoints_, ejecución paso a paso, inspeccionar variables,..etc. * [Flutter inspector](https://docs.flutter.dev/development/tools/devtools/inspector) , disponible en las DevTools y también directamente en el **IDE** Android Studio/IntelliJ (Flutter/Dart plugin). El inspector nos permite examinar visualmente el widget tree, inspeccionar propiedades concretas de widgets, ...etc. [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/herramientas-para-debugging.-logs#devtools) Logs ------------------------------------------------------------------------------------------------------------------------------------------------------- Podemos registrar **mensajes** **de** **log** para realizar debugging desde el código. Podremos verlos: * Desde la pestaña "**Logging** **View"** de las **Devtools** o * En la **consola**. Tenemos dos **opciones**: 1. Llamar directamente a la función `**print('my_message')**` que imprimirà el mensaje en la Consola. En Logcat se registrará del tipo `Info`: "`I/flutter (11714) :` " 2. Utilizar la función `**log()**` de `dart:developer` que nos permite **estructurar** mejor la información de _log_. Copy void log( String message, { DateTime? time, int? sequenceNumber, int level = 0, String name = '', Zone? zone, Object? error, StackTrace? stackTrace, }); **Ejemplo**: Copy import 'dart:convert'; import 'dart:developer' as developer; void main() { developer.log( 'Main started', name: 'main()', ); } [PreviousHot Reload - Hot Restart - Full Restart](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/hot-reload-hot-restart-full-restart) [Next4\. Conceptos fundamentales en Flutter](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter) Last updated 1 year ago --- # Stateless widget | 1. Introducción a Flutter Los widgets **stateless** extienden de la clase `**StatelessWidget**` y son **inmutables** y, por ello, una vez creados, ya no van a cambiar sus propiedades durante la ejecución de la aplicación. * Todos sus atributos deberían declararse _final_ (aunque Dart no obliga) * Son widgets que se optimizan internamente por el runtime de Flutter * Deben de utilizarse siempre que el estado del widget no vaya a cambiar, es decir, depende únicamente de sus datos internos. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateless-widget#ejemplo-1) **Ejemplo 1** Creamos una aplicación MaterialApp compuesta por un **stateless** **widget:** **HomePage**, donde **count** es un atributo entero declarado como _final_ que no cambiará en tiempo de ejecución. Copy import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return const MaterialApp( home: Homepage(count: 10), ); } } class Homepage extends StatelessWidget { final int count; const Homepage({required this.count}); @override Widget build(BuildContext context) { return Text('Count = $count'); } } ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FLJHeGkz7sHyI47fR5qdx%252Fimage.png%3Falt%3Dmedia%26token%3D796c0ac9-483f-4302-9bdd-0b8fcf6f29c8&width=768&dpr=4&quality=100&sign=45c70928&sv=2) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateless-widget#ejemplo-2) Ejemplo 2 En este segundo ejemplo vamos a modificar el valor de `count` y comprobar si se visualiza en pantalla el valor actualizado. * Para ello, **sustituimos** el código de **Homepage** del **Ejemplo 1** por el siguiente código donde se incrementa el valor de `count` al pulsar el botón. Copy class Homepage extends StatelessWidget { int count; Homepage({required this.count}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Example of Stateless widget'),), body: ElevatedButton( onPressed: () { count++; print(count); }, child: Text('Try to increment, COUNT= ${count}'),), ); } } ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FOOzXjPnwhQtuSwWg27rV%252Fimage.png%3Falt%3Dmedia%26token%3D0bb8e176-7d98-48e1-b29f-c3dc12154351&width=768&dpr=4&quality=100&sign=98f2255b&sv=2) Si lo **ejecutamos**, comprobaremos que pulsando el botón se imprime en la consola el valor real de `count` pero en realidad, como es un **widget** **inmutable,** Flutter ignora cualquier cambio y **no se actualiza su valor en la UI**. (\-> necesitaremos un widget Stateful) [PreviousWidgets](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets) [NextStateful widget](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget) Last updated 11 months ago --- # Estructura de una Aplicación Flutter | 1. Introducción a Flutter [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/estructura-de-una-aplicacion-flutter#creamos-una-aplicacion-basica-en-flutter) Creamos una aplicación bàsica en Flutter ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Creamos un **nuevo** **proyecto** Flutter (o abrimos uno existente) y **sustituimos** el **código** de _main.dart_ por un código más sencillo: Copy import 'package:flutter/material.dart'; // 1. Usamos material para la UI // 2. runApp() (con notación arrow) inicia la aplicación Flutter y muestra la UI en pantalla void main() => runApp(MyApp()); class MyApp extends StatelessWidget { // 3. Nuestra aplicación se compone de widgets @override Widget build(BuildContext context) { // 4. El método build() determina cómo construir este widget return MaterialApp( home: Scaffold( // 5. Widget que proporciona una app bar y un body para nuestra pantalla inicial appBar: AppBar( title: const Text('Welcome to Flutter'), ), body: const Center( // 6. Centrará en su contenedor (pantalla) widget child child: Text('Hello World !!'), ), ), ); } } > **Nota**: Eliminaremos el código del test de ejemplo de la función main() del fichero _test/widget\_test.dart_ Si lo **ejecutamos**, obtendremos una aplicación similar a la siguiente imagen: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FBnBkQlTR5PLTA0EIXPSS%252Fimage.png%3Falt%3Dmedia%26token%3Df5f07204-9b20-4348-83fa-03266ab79940&width=300&dpr=4&quality=100&sign=b2d86cef&sv=2) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/estructura-de-una-aplicacion-flutter#directorios-y-ficheros-del-proyecto-flutter) Directorios y ficheros del proyecto Flutter ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FqRyZTAbrOKCGm2qSSjza%252Fimage.png%3Falt%3Dmedia%26token%3D8c768b20-6884-43f9-929e-c3504540488f&width=768&dpr=4&quality=100&sign=164401c5&sv=2) Vista del proyecto Flutter desde Android Studio * `**.dart_tool/**` - Directorio autogenerado tras ejecutarse _pub get_. Contiene el fichero _package\_config.json_ que especifica la versión de cada paquete y su localización. * `**.idea/**` - Directorio que contiene la configuración de Android Studio para el proyecto. * `**android/**` - Directorio que contiene el código autogenerado para el proyecto Android cuando estamos desarrollando la aplicación flutter para Android. Cuando el proyecto Flutter se compila a código nativo, se inyectará dentro de este proyecto Android para generar la aplicación Android nativa. * `ios/` - Directorio que contiene el código autogenerado para el proyecto iOS mientras desarrollamos la aplicación Flutter para iOS. Cuando el proyecto Flutter se compila a código nativo, se inyectará dentro de este proyecto iOS para generar la aplicación iOS nativa. > Para compilar la aplicación Flutter para iOS se precisará de macOS. Por ello, este directorio sólo estará disponible cuando el proyecto se cree en un Mac. * `web/` - Este directorio autogenerado contiene el código del proyecto Web cuando creamos la aplicación Flutter para web. Cuando el proyecto Flutter se compila a código nativo, se inyectará dentro de este proyecto web para generar la aplicación web nativa. * `**build/**` \- Directorio autogenerado que contiene el código compilado de la aplicación Flutter. Se actualiza de forma incremental por motivos de rendimiento (compilar cada vez por completo la aplicación tomaría mucho tiempo) * `**lib/**` - (library) Este es el directorio principal cuando estamos creando nuestra aplicación Flutter. Contendrá todos los ficheros Dart que utilizan el framework de flutter. Por defecto, contiene el fichero `**main.dart**` que es el punto de entrada de la aplicación Flutter. * `test/` - Directorio con el código Dart para los tests automáticos de nuestra aplicación Flutter. El fichero _widget\_test.dart_ contiene código de test de ejemplo. * `.gitignore` - Fichero que contiene la lista de ficheros y directorios que serán ignorados por Git. * `.metadata` - Fichero autogenerado por las herramientas de flutter que contiene metadatos o propiedades de nuestra aplicación flutter. * `helloflutter.iml` - Fichero con el mismo nombre del proyecto. Contiene configuraciones adicionales del proyecto que utiliza Android studio. * `**pubspec.yaml**` - Fichero de configuración del proyecto Flutter que utiliza Pub, la herramienta de gestión de paquetes de Flutter. * `pubspec.lock` - Fichero autogenerado por Pub (Flutter package manager) a partir del fichero pubspec.yaml que indica las versiones de los paquetes utilizadas en el proyecto. * `README.md` - Fichero autogenerado al crear el proyecto que contiene una descripción inicial. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/estructura-de-una-aplicacion-flutter#main.dart-explicacion-del-codigo) main.dart: Explicación del código Copy import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: const Text('Welcome to Flutter'), ), body: const Center( child: Text('Hello World !!'), ), ), ); } } * **Linea (1):** importamos en la aplicación el package **Material** para la interfaz de usuario: `import 'package:flutter/material.dart` **Material** es el paquete para desarrollar la UI siguiendo las directrices de diseño de Material Design especificadas por Google. [https://m3.material.io/](https://m3.material.io/) * **Linea (3):** la función **main()** es el punto de entrada de la aplicación Flutter que llama a la función `**runApp**` la cual se encarga de construir la **jerarquía de widgets** (tree) a partir del widget que se le pasa como instancia: MyApp: `void main() => runApp(MyApp());` > La función _runApp_ asociará el widget MyApp a la pantalla (será el widget root). * **Linea (5):** La **clase** **MyApp** es un widget stateless y se usa para crear la UI. Esta clase ha de sobrescribir el método _**build**_ el cual será llamado por el framework de Flutter para construir la UI de la aplicación. > La aplicación en sí misma es un _widget (_en este caso, _stateless_ _)_. La mayoria de los componentes de la aplicacion de Flutter son widgets: `stateless` o `stateful`. * **Linea (7):** El método sobrescrito `**build**` devuelve un widget del tipo _**MaterialApp**_ que crea la UI principal de la aplicación. En este caso, tiene definida la propiedad `**home**` que specifica la **UI** de la aplicación con el widget: `**Scaffold:**` * El widget `Scaffold` proporciona la UI básica para una aplicación con Material design que contiene las propiedades: * `**appBar**`: establece la barra de la application. * `**body**`: establece el widget `**Center**` para mostrar el contenido del widget `Scaffold` : * `Center:` widget que se usa para centrar el _child_ widget que se le proporciona: _Text. En este caso, se_ mostrará un texto en el centro de la pantalla. Con MaterialApp podremos: navegar entre pantallas (route navigation), establecer el tema de la aplicacion así como otras configuraciones. [Previous4\. Conceptos fundamentales en Flutter](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter) [NextWidgets](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets) Last updated 11 months ago --- # Ciclo de Vida | 1. Introducción a Flutter Es **fundamental** familiarizarse con el **ciclo** **de** **vida** de la aplicación en Flutter de forma que comprendamos cómo se **crea**, se **renderiza**, **actualiza** y se **destruye**. En Flutter, distinguiremos entre: * El ciclo de vida de la **aplicación** * El ciclo de vida de los **widgets**, en concreto de StatefulWidget. [PreviousStateful widget](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget) [NextCiclo de Vida de los Widgets](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-los-widgets) Last updated 1 year ago --- # 5. Recomendaciones (best practices) | 1. Introducción a Flutter [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices#nombrado-del-ficheros-y-directorios) **Nombrado del ficheros y directorios** ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Para nombrar los **ficheros** y **directorios**, utilizaremos **siempre** **minúsculas** y como **separador,** el guión bajo `**_**` `(lowercase_underscore)` [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices#organizacion-de-los-directorios-estructura-propuesta) Organización de los directorios: estructura propuesta ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * No hay una forma estandarizada para estructurar nuestra aplicación. * Pero, a medida que un proyecto Flutter crezca deberemos de tener una estructura clara y organizada de todos sus ficheros de forma que se facilite el trabajo en equipo así como el mantenimiento de la aplicación (no debemos perder tiempo buscando un widget o viendo dónde situar uno nuevo). * Todo esto repercutirá al final en un mejor rendimiento de la aplicación Copy assets // recursos propios que utiliza de la aplicación |_ images |_ videos |_ fonts ... lib |_ cloud_functions // código para obtener datos de servidores (ej: abrir URL) |_ screens // (también podemos nombrarlas: pages o windows) // código UI: para las pantallas de nuestra aplicación // se puede organizar en subdirectorios: login, home, others |_ providers // código que transforma los datos recibidos desde el exterior (network) // en otros objetos de forma que puedan visualizarse/usarse. // (ej: json de info meteorológica recibido se transforma // en una lista de objetos weatherInfo) |_ models // código para los datos que provienen de servidores, del usuario, etc. // (ej: weatherInfo -> lat, lon, temperature, humidity,...) |_ utilities // código que contiene la lógica de negocio (business logic) // para toda nuestra aplicación. |_ widgets // widgets que se van a utilizar varias veces en distintas partes // de la aplicación. // Ejemplo: Listview y LisTile para mostrar los datos recibidos. [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices#import-relativo-vs-import-package) Import relativo vs import package ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- La convención y **mejores** **prácticas** en Flutter prefiere usar **imports** **relativos** al package **para** **código** **dentro** de tu **propio** proyecto aunque tenemos varias **alternativas**: 1. **Imports dentro de tu proyecto (lib/):** Copy // ✅ EL MEJOR: Usar imports relativos para archivos en lib/ import 'screens/home_screen.dart'; import 'widgets/custom_button.dart'; import 'utils/constants.dart'; 1. **Imports de paquetes externos:** Copy // ✅ CORRECTO: Usar package: para dependencias externas import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; 1. **Imports de tu propio paquete:** Copy // ✅ TAMBIÉN VÁLIDO: Usar package: para tu propio código import 'package:mi_app/screens/home_screen.dart'; import 'package:mi_app/widgets/custom_button.dart'; [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices#por-que-se-prefieren-los-imports-relativos-para-codigo-de-tu-proyecto) ¿Por qué se prefieren los imports relativos para código de tu proyecto? ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Razones: * Más **cortos** y **limpios** * Más **fáciles** de **mover** archivos (**refactoring**) * **Menor** probabilidad de **errores** al renombrar el package * Es la **convención** **más** **común** en la comunidad Flutter [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices#cuando-usar-package) ¿Cuándo usar `package?` ---------------------------------------------------------------------------------------------------------------------------------------------------- 1. Siempre para importar **dependencias** **externas** 2. Cuando importas desde **test/** código de lib/ Ejemplo:[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices#ejemplo) Copy mi_proyecto/ ├── lib/ │ ├── src/ │ │ └── calculator.dart │ └── main.dart └── test/ └── calculator_test.dart // En calculator_test.dart DEBES usar package: import 'package:mi_proyecto/src/calculator.dart'; // ✅ CORRECTO // NO puedes usar: import '../lib/src/calculator.dart'; // ❌ INCORRECTO Esto es porque los archivos en `test/` están fuera del directorio `lib/` y necesitan referenciar el código como si fuera un paquete. 1. Cuando tienes **múltiples** **packages** en el mismo proyecto. Ejemplo[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices#ejemplo-1) Copy mi_proyecto/ ├── packages/ │ ├── feature_a/ │ │ └── lib/ │ │ └── feature_a.dart │ └── feature_b/ │ └── lib/ │ └── feature_b.dart └── main_app/ └── lib/ └── main.dart // En main.dart cuando quieres usar feature_a: import 'package:feature_a/feature_a.dart'; // ✅ CORRECTO Esto es común en **proyectos** **grandes** donde divides funcionalidades en packages separados dentro del mismo proyecto. 1. Cuando estás creando un **package** para **publicar** [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices#best-practices-articulos) Best Practices - Artículos ------------------------------------------------------------------------------------------------------------------------------------------------------------ [![Logo](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A304%3A304%2F10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156&width=20&dpr=4&quality=100&sign=d77d307f&sv=2)Flutter best practices for Improve PerformanceMedium](https://inficial.medium.com/flutter-best-practices-for-improve-performance-7e21e14efebb) [![Logo](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fwww.mindinventory.com%2Fblog%2Fwp-content%2Fuploads%2F2024%2F02%2Fmi-icon-transparent.png&width=20&dpr=4&quality=100&sign=d90ae427&sv=2)12 Best Practices to Simplify Flutter App Development in 2025MindInventory](https://www.mindinventory.com/blog/flutter-development-best-practices/) 12 Best Practices to Simplify Flutter App Development [![Logo](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A304%3A304%2F10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156&width=20&dpr=4&quality=100&sign=d77d307f&sv=2)Benefits of SOLID Principles in Flutter Development: An OverviewMedium](https://medium.com/flutter-community/benefits-of-solid-principles-in-flutter-development-an-in-depth-guide-19697309e854) SOLID principles in Flutter [PreviousEjemplo de uso de keys](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/responding-to-widget-lifecycle-events-keys/ejemplo-de-uso-de-keys) [Next6\. Tips & Tricks](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/6.-tips-and-tricks) Last updated 11 months ago --- # Desde Visual Studio Code | 1. Introducción a Flutter **Atención**: Las extensiones de Dart y Flutter han de estar instaladas y habilitadas en Visual Studio Code. Toda la información y detalles: [https://flutter.dev/docs/get-started/test-drive?tab=vscode](https://flutter.dev/docs/get-started/test-drive?tab=vscode) [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-visual-studio-code#creamos-un-nuevo-proyecto-flutter) Creamos un nuevo proyecto Flutter ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1. Abrimos Visual Studio Code (VSCode) 2. Accedemos a la paleta de comandos: **View -> Command Palette** o `**Ctrl/Cmd + Shift + P**` 3. Escribimos “**flutter**” y seleccionamos: **Flutter: New Project**. > ℹ️**Atención: Organización(Package) y lenguaje para Android/iOS** > > La aplicación se crea siempre por defecto con el nombre de package _com.example. P_odemos cambiarlo en la Configuración de Flutter en VSCode: > > _Preferencias --> Configuración --> Extensiones -->Dart --> Flutter_ > > * Cambiar Package: sección _Dart: Flutter Create Organization y_ pulsamos sobre _"Editar en settings.json"_ y añadimos a la lista _json_ (por ejemplo, en primer lugar) el nombre de nuestra organización. Por ejemplo, para _dam.empar_ seria: `"dart.flutterCreateOrganization": "dam.empar",` > > * El lenguaje por defecto lo podemos cambiar en: _Dart: Flutter Create Android Language_ y _Dart: Flutter Create IOSLanguage_ > ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F9GYr7oW6afp8ZndOMcRF%252Fimage.png%3Falt%3Dmedia%26token%3Df8049f01-6002-435b-aaa5-e38b8d3837db&width=768&dpr=4&quality=100&sign=950d8919&sv=2) 4\. Seleccionamos el **tipo** de proyecto Flutter: **Application** ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252Fk58FWf3pquFy3gDF7ZWP%252Fimage.png%3Falt%3Dmedia%26token%3Da5489162-63d1-4ef4-b4a4-9d1f530f0cac&width=768&dpr=4&quality=100&sign=b1eecd02&sv=2) 5\. Creamos o seleccionamos el **directorio** **padre** donde se creará automáticamente la **nueva** **carpeta** para el proyecto. 6\. Escribimos el **nombre** del **proyecto**: `hellofluttervs`, y pulsamos **Enter**. 7\. Esperamos a que se cree el proyecto y se abrirá automáticamente en el editor de código el fichero `main.dart` ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F5NIay6CxuAySePok8i5Y%252Fimage.png%3Falt%3Dmedia%26token%3Df6412be1-3fd1-40ce-8e8e-3a7903c9fee0&width=768&dpr=4&quality=100&sign=c5cffb57&sv=2) [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-visual-studio-code#ejecutamos-la-aplicacion-flutter) Ejecutamos la aplicación Flutter -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Desde la barra de estado tenemos un **selector** **de** **dispositivos** (podemos ver que Chrome es el dispositivo sobre el que se ejecutará la aplicación por defecto) ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FD6JhxAOcY85PAh8Myn89%252Fimage.png%3Falt%3Dmedia%26token%3D834a3077-0111-4186-bea0-cc8af8d4d29a&width=768&dpr=4&quality=100&sign=331e3ced&sv=2) * Para **seleccionar** otro dispositivo o emulador, haremos clic sobre el selector de dispositivos: se abrirá la _paleta de comandos_ con una ventana emergente que muestra la lista de dispositivos reales y emuladores disponibles ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252Fv5f0fYwu7hSiDr3Tc9eU%252Fimage.png%3Falt%3Dmedia%26token%3Dad084127-4dd8-47ba-bda1-f9337c50653a&width=768&dpr=4&quality=100&sign=38853136&sv=2) * Seleccionamos un dispositivo/emulador de la lista (si no está en ejecucición, se arrancará el emulador seleccionado) * Ejecutamos la aplicación desde: **Run --> Start Debugging** or pulsamos `**F5**`**.** * Esperamos a que se compile y se despliegue en el dispositivo: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252Fri4KRVwDH62NLPtEuhDc%252Fimage.png%3Falt%3Dmedia%26token%3D2cb79092-2f5d-4f78-8f47-1b38945d6ab1&width=300&dpr=4&quality=100&sign=293abf89&sv=2) * Nos aparecen las herramientas de depuración: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FSjD0QKEbtlIys3rpmzjd%252Fimage.png%3Falt%3Dmedia%26token%3Ddb17ae42-887e-4cff-beca-c586f0b387e2&width=768&dpr=4&quality=100&sign=3daa158a&sv=2) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-visual-studio-code#probamos-hot-reload) Probamos hot reload Si **modificamos** el título de la barra de la aplicación y **guardamos** (o pulsamos en hot reload), veremos de inmediato el resultado en ejecución sin perder el estado: ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FMG6hAgqxgDSv64lQGGmr%252Fimage.png%3Falt%3Dmedia%26token%3D799ab8d5-1c90-47df-ae3c-9874148650ce&width=300&dpr=4&quality=100&sign=9955aba8&sv=2) [PreviousDesde Android Studio](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-android-studio) [NextDesde el DartPad](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/3.-primera-aplicacion-en-flutter/desde-el-dartpad) Last updated 1 year ago --- # Ciclo de Vida de los Widgets | 1. Introducción a Flutter ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FFksAREdG55Met4DXr0da%252Fimage.png%3Falt%3Dmedia%26token%3D65f40479-6a78-4668-971b-377ff947b4c9&width=768&dpr=4&quality=100&sign=1a5ec7b5&sv=2) [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-los-widgets#ciclo-de-vida-statelesswidget) Ciclo de Vida StatelessWidget ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FjJk9LuaKI1Cc9yvDXbhI%252Fimage.png%3Falt%3Dmedia%26token%3D9050dd99-aff0-412f-b469-82306387b60a&width=300&dpr=4&quality=100&sign=8aa366fb&sv=2) Widget **inmutable**. El método `build()` se llamará en estos casos: * Cuando el widget se inserta en el árbol de widgets, o * Cuando el widget padre cambie su configuración, o * Cuando un [InheritedWidget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html) del cual depende también cambia. [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-los-widgets#ciclo-de-vida-statefulwidget) Ciclo de Vida StatefulWidget ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252Fm0olOHGqv2FqVGyTuMsy%252Fimage.png%3Falt%3Dmedia%26token%3Dd211e7e7-9592-426e-9908-92e9bb0fdacb&width=768&dpr=4&quality=100&sign=93f658ed&sv=2) Explicación: [https://medium.flutterdevs.com/app-lifecycle-in-flutter-c248d894b830](https://medium.flutterdevs.com/app-lifecycle-in-flutter-c248d894b830) **createState()**: Se llama cuando creamos un nuevo StatefulWidget. Se encarga de crear el estado mutable para este widget instanciando el objeto State asociado a este widget. **initState()**: Se llama después del constructor y sólo una vez para cada objecto State. Aquí podremos inicializar datos, listeners, etc. **didChangeDependencies()**: Se llama después de initState() y también cuando se actualiza algún objeto del cual dependa, por ejemplo un InheritedWidget u otras dependencias (cambio de tema, orientación del dispositivo, etc.) > build() se ejecutará de forma inmediata, así que raramente lo implementaremos. A no ser que tengamos un proceso costoso, como obtener datos de un servidor en red, y que no se ha de hacer en cada build(), sino sólo cuando cambia el InheritedWidget. **build()**: Devuelve el Widget que se mostrará en pantalla. Se llama de forma frecuente (después de iniState(), tras setState(),....) cuando se necesita renderizar los UI widgets en pantalla. Este método solo debe encargarse de construir el widget, nada más. El framework se encargará de optimizar su inserción en el árbol de widgets. **didUpdateWidget**(): Se llama siempre que se cambia el Widget asociado a este objeto State por un nuevo Widget del mismo _runtimeType_ y _key_ que el anterior. El framework asocia State con el nuevo Widget. Después de este método, se llama siempre a _build()._ _\--> Deberemos sobrescribir didUpdateWidget para actualizar correctamente el estado con los datos del nuevo widget que se ha creado (o seguiremos mostrando el estado con los datos del anterior widget)_ [https://api.flutter.dev/flutter/widgets/State/didUpdateWidget.html](https://api.flutter.dev/flutter/widgets/State/didUpdateWidget.html) "If the parent widget rebuilds and request that this location in the tree update to display a new widget with the same [runtimeType](https://api.flutter.dev/flutter/widgets/State/dart-core/Object/runtimeType.html) and [Widget.key](https://api.flutter.dev/flutter/widgets/State/widgets/Widget/key.html) , the framework will update the [widget](https://api.flutter.dev/flutter/widgets/State/widgets/State/widget.html) property of this [State](https://api.flutter.dev/flutter/widgets/State/widgets/State-class.html) object to refer to the new widget and then call this method with the previous widget as an argument." **setState()**: Es la forma de notificar al framework de Flutter que los datos, el estado, han cambiado y que el widget debe reconstruirse. Este método toma como argumento una función callback que se encarga de actualizar los datos (ha de ser un proceso rápido). **deactivate()**: Se llama cuando momentáneamente se elimina este objeto State del árbol de widgets (los objetos State pueden moverse de lugar en el árbol), però podría ser reinsertado antes de que acabe el _frame_ actual. **dispose()****:** Se llama cuando este objeto State se va a eliminar de forma permanente del árbol de widgets. En este método es donde deberíamos cancelar animaciones, streams, cerrar conexiones, etc. Más información: [https://medium.com/@resand/ciclo-de-vida-de-flutter-para-desarrolladores-android-e-ios-4bc4dfcd7169](https://medium.com/@resand/ciclo-de-vida-de-flutter-para-desarrolladores-android-e-ios-4bc4dfcd7169) [https://flutterbyexample.com/lesson/stateful-widget-lifecycle](https://flutterbyexample.com/lesson/stateful-widget-lifecycle) [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-los-widgets#actividad-de-video-como-renderiza-flutter-los-widgets) Actividad de vídeo: ¿Cómo renderiza Flutter los widgets? ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- En el siguiente **vídeo**, se describe **cómo** **trabaja** **Flutter** **internamente**, lo cual, le permite ser muy **eficiente**. Se explica la relación entre las jerarquías **Widget**, **Element** y **RenderObject**. **VÍDEO (26 mins): How Flutter render widgets?** [https://www.youtube.com/watch?v=996ZgFRENMs&list=PLjxrf2q8roU3wk7CDw4RfV3mEwOJbjx1k](https://www.youtube.com/watch?v=996ZgFRENMs&list=PLjxrf2q8roU3wk7CDw4RfV3mEwOJbjx1k) ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FTqJK2MFKiYkmbzql5Ua9%252Fimage.png%3Falt%3Dmedia%26token%3D7fe235a2-f9d8-4f2e-9b3c-5d6e613a798f&width=768&dpr=4&quality=100&sign=42def06e&sv=2) Pregunta sobre el vídeo... Respuesta ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-los-widgets#por-que-flutter-mantiene-internamente-3-arboles-widget-element-y-render-object) ¿Por qué Flutter mantiene internamente 3 árboles? Widget, Element y Render Object * Los tres árboles trabajan juntos para permitir a Flutter manejar **eficientemente** las actualizaciones de la interfaz de usuario (UI). * Cuando se realiza un **cambio** en la interfaz de usuario, Flutter crea un **nuevo** **árbol** de **widgets**, **actualiza** el **árbol** de **elementos** para reflejar cualquier cambio y luego utiliza el **árbol** de **renderizado** para **actualizar** la **interfaz** de usuario en la pantalla. Esto permite a Flutter realizar actualizaciones de la interfaz de usuario de manera **eficiente** y **rápida.** [PreviousCiclo de Vida](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida) [NextCiclo de vida de la aplicación](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-la-aplicacion) Last updated 11 months ago --- # Stateful widget | 1. Introducción a Flutter Un widget **stateful** extiende de la clase `**StatefulWidget**`. Contiene datos que pueden **cambiar** en tiempo de ejecución y que afectarán a la **visualización** de la UI, que deberá ser actualizada debidamente. Los **StatefulWidgets** resultan útiles cuando la parte de la UI que estamos describiendo puede cambiar. Por ejemplo: el usuario pulsa un botón y el texto de un widget Text debe actualizarse. El **estado** del widget viene dado por sus propiedades (datos). [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget#implementacion-de-un-statefulwidget) Implementación de un StatefulWidget ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Para **implementar** un S_tateful widget_, necesitamos definir dos clases: * Una clase que extiende de la clase `**StatefulWidget**` que creará una instancia de la clase `State.` * Una clase que extiende de `**State**` que contiene: * El **estado** _**mutable**_ para este widget * El método `**build()**` Desde el objeto `**State**` podremos acceder a BuildContext directamente con la **propiedad** `_**context**_`, así como a su widget asociado con la **propiedad** `_**widget**_`. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget#como-actualizar-el-estado-del-widget-y-hacerlo-visible-en-pantalla) ¿Cómo actualizar el estado del widget y hacerlo visible en pantalla? Cada vez que **actualicemos** las propiedades del widget, es decir, su **estado**, deberemos llamar al método `**setState(..)**` que indica al framework de Flutter que debe **redibujar** de nuevo el widget. `setState(..)` provocará que el framework de Flutter llame de nuevo al método `**build()**` de este objeto `State` el cual devolverá un **nuevo** **widget** con los datos **actualizados** (**nuevo** **estado**) y que ya podremos ver en pantalla. [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget#ejemplo-1-widget-con-estado-para-mostrar-un-contador) **Ejemplo 1: Widget con estado para mostrar un contador** --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Vamos a crear una aplicación `MaterialApp` compuesta por **widget** **con** **estado** que contiene un botón, que ocupará toda la pantalla, y que muestra un texto con el valor actual de un contador. **Funcionamiento**: * Al pulsar sobre el botón se incrementará el valor del contador. * Pero, si queremos ver en pantalla el contador actualizado, se debe **ejecutar** el método `**setState(...)**` que provoca que el framework de Flutter renderize de nuevo el botón (se llamará de nuevo a build()) mostrando así en pantalla el nuevo valor del contador. ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FlDKIpCXYqamMnAO5iRlN%252Fimage.png%3Falt%3Dmedia%26token%3D60f0646c-8f11-4d18-85dd-74eaba5481a6&width=768&dpr=4&quality=100&sign=2ee5a62&sv=2) El **código** sería: Copy import 'package:flutter/material.dart'; void main() => runApp(App()); class App extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Homepage(), ); } } class Homepage extends StatefulWidget { @override State createState() => _HomepageState(); } class _HomepageState extends State { int _count = 0; @override Widget build(BuildContext context) { return ElevatedButton( child: Text('Pressed: $_count'), onPressed: _increaseCounter, // o directamente: () => setState(() => count++), ); } void _increaseCounter() => setState(() => _count++); } ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget#explicacion-del-codigo) **Explicación del código**: * `**State:**` La clase _state_ extiende de `State` con `T` siendo del tipo del correspondiente `StatefulWidget`. La clase `state` creada es exclusiva para `T` y no se puede reutilizar en otro `StatefulWidget` El propio widget `Stateful` es **inmutable**, es su objeto `State` el que persiste durante el tiempo de vida del widget. * Cuando queremos cambiar el estado del widget, debemos llamar a _**setState**__():_ indicamos así al framework que redibuje (re-render) el widget, se llamará al `**build**` de este widget (y el de todos los widgets del árbol que se puedan ver implicados). > **setState(...)**: toma como argumento una función del tipo: `VoidCallback` > > Un widget stateless puede contener widgets stateful y viceversa. * `**build():**` devuelve un `ElevatedButton` que tiene asignado en `onPressed` el método _\_increaseCounter_ que se llamará al pulsarlo. _\_increaseCounter_ se encargará de llamar a setState() desde donde se incrementa el contador. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget#por-que-se-necesita-un-objeto-state-separado-para-un-statefulwidget) ¿Por qué se necesita un objeto _State_ separado para un _StatefulWidget_? La razón es porque en Flutter estos objetos tienen ciclos de vida diferentes: * Los `Widgets` son objetos **temporales**, utilizados para construir una visualización (UI) de la aplicación en su estado actual. * Los objetos `State`, por otra parte, son **persistentes** entre diferentes llamadas a `build()`, de esta forma, los widgets pueden recordar la información (**mantienen su estado entre llamadas a build()**). > En aplicaciones más complejas, cada widget de la jerarquía tiene unas responsabilidades concretas; por ejemplo, un widget podría representar la interfaz de usuario para recoger una información específica (por ejemplo, fecha y lugar) mientras que otro widget se encargaria de usar esa información para cambiar la visualización de la UI. En Flutter, las **notificaciones** **de** **cambio** **fluyen** **hacia** "**arriba**" de la jerarquía de widgets, mientras que la **visualización** **del** **estado** **actual** **fluye** hacia "**abajo**", hacia los widgets stateless que se encargan de visualizar la UI (en el estado actual que tenga el widget). El objeto común que redirige este flujo es el `**State**`. [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget#ejemplo-2-flujos-de-notificaciones-de-actualizacion) **Ejemplo 2: Flujos de notificaciones de actualización** ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Veamos un ejemplo más complejo del **contador** donde se vean cómo funcionan los flujos de notificación y de visualización (re-rendering). ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252F38D94FPDQZTgY7HC8sko%252Fimage.png%3Falt%3Dmedia%26token%3D3dedbab6-b98b-47cd-b2e6-269c41a8be15&width=300&dpr=4&quality=100&sign=3f744072&sv=2) La **aplicación** **se** **compone** de los siguientes widgets: * Dos widgets _stateless_, cada uno cumple su función, separando responsabilidades: * `CounterDisplay` : Muestra un texto con el valor del contador: * `CounterIncrementor` : Contiene un botón, que al pulsarlo, llamará a una función (callback) que incrementará el valor del contador. * El widget _stateful_ `Counter` se compone de los dos widgets stateless anteriores y contiene el estado: el valor del contador (que se incrementará al pulsar el botón). El resultado es similar al Ejemplo 1 pero al **separar** **responsabilidades** se permite que la **complejidad** se **encapsule** en los widgets individuales a la vez que se mantiene la **simplicidad** en el widget padre `Counter`. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget#veamos-el-codigo) Veamos el **código**: Copy import 'package:flutter/material.dart'; void main() { runApp( const MaterialApp( home: Scaffold( body: Center( child: Counter(), ), ), ), ); } class CounterDisplay extends StatelessWidget { const CounterDisplay({required this.count, Key? key}) : super(key: key); final int count; @override Widget build(BuildContext context) { return Text('Count: $count'); } } class CounterIncrementor extends StatelessWidget { const CounterIncrementor({required this.onPressed, Key? key}) : super(key: key); final VoidCallback onPressed; // VoidCallback type: no args and no returned data @override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, child: const Text('Increase Counter'), ); } } class Counter extends StatefulWidget { const Counter({Key? key}) : super(key: key); @override State createState() => _CounterState(); } class _CounterState extends State { int _counter = 0; // setState(..): makes that framework calls build() void _increment() => setState(() => ++_counter); @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [\ CounterDisplay(count: _counter),\ const SizedBox(height: 16, ), // to make same room between widgets\ CounterIncrementor(onPressed: _increment), // set callback\ ], ); } } ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateful-widget#contadores-independientes) Contadores independientes A partir de nuestro statefulwidget `Counter`, podríamos crearnos fácilmente **varios** **contadores** **independientes**, cada uno con su propio objeto State: Ejemplo con múltiples contadores Código ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FOrpL1j0XPbt4xAeXKHxw%252Fimage.png%3Falt%3Dmedia%26token%3D2f6975de-1927-4a15-90f8-b0df3ca8ad6c&width=300&dpr=4&quality=100&sign=526cd358&sv=2) Copy import 'package:flutter/material.dart'; void main() { runApp(const MaterialApp( home: Scaffold( body: const MultipleCounters(), ), )); } class MultipleCounters extends StatelessWidget { const MultipleCounters({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [\ Counter(), SizedBox(height: 20), Counter(), SizedBox(height: 20,), Counter(),\ ], )); } } // same code: class CounterDisplay extends StatelessWidget { const CounterDisplay({required this.count, Key? key}) : super(key: key); final int count; @override Widget build(BuildContext context) { return Text('Count: $count'); } } class CounterIncrementor extends StatelessWidget { const CounterIncrementor({required this.onPressed, Key? key}) : super(key: key); final VoidCallback onPressed; // VoidCallback type: no args and no returned data @override Widget build(BuildContext context) { return ElevatedButton( onPressed: onPressed, child: const Text('Increase Counter'), ); } } class Counter extends StatefulWidget { const Counter({Key? key}) : super(key: key); @override State createState() => _CounterState(); } class _CounterState extends State { int _counter = 0; void _increment() => setState( () => ++_counter); // setState(..): makes that framework calls build() @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [\ CounterDisplay(count: _counter),\ const SizedBox(\ height: 16,\ ), // to make same room between widgets\ CounterIncrementor(onPressed: _increment), // set callback\ ], ); } } [PreviousStateless widget](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/widgets/stateless-widget) [NextCiclo de Vida](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida) Last updated 11 months ago --- # Ejemplo de uso de keys | 1. Introducción a Flutter Ejemplo sencillo con dos Widget Container que guardan su color y el texto que muestran en su objeto State. Cuando pulsamos el botón, se intercambian los containers y gracias al uso de keys también se muestra el estado correcto. When to Use Keys - Flutter Widgets 101 Ep. 4: [https://www.youtube.com/watch?v=kn0EOS-ZiIc](https://www.youtube.com/watch?v=kn0EOS-ZiIc) [PreviousResponding to widget lifecycle events, Keys](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/responding-to-widget-lifecycle-events-keys) [Next5\. Recomendaciones (best practices)](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/5.-recomendaciones-best-practices) Last updated 2 years ago --- # Ciclo de vida de la aplicación | 1. Introducción a Flutter En una aplicación Flutter, tendremos acceso a una selección de los eventos del ciclo de vida de la aplicación (en una app nativa tendríamos más eventos). [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-la-aplicacion#estados) Estados ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Los diferentes **estados** en los que puede estar la aplicación (ciclo de vida) vienen determinados por el `enum` [`AppLifecycleState`](https://api.flutter.dev/flutter/dart-ui/AppLifecycleState.html) y son los siguientes: * **detached**: La aplicación **no tiene interfaz visible**, está en proceso de creación/destrucción. * **resumed**: La aplicación está **visible** e **interactuando** con el usuario. (_Resumed_ de Android) * **inactive**: La aplicación es **visible** **pero** **no** **recibe** **interacción** del usuario: split-screen, un diálogo del sistema aparece, una llamada de teléfono,.. (Sería similar a un estado _Paused_ de Android) * **hidden:** La aplicación **no** es **visible,** está a punto de ser pausada. * **paused**: La aplicación **no** es **visible**, está en segundo plano, y **no** **interactúa** con el usuario. ( _Stopped_ de Android) [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-la-aplicacion#eventos-del-ciclo-de-vida) Eventos del ciclo de vida ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-la-aplicacion#primera-forma-widgetsbindingobserver) Primera forma: `**WidgetsBindingObserver**` Para **capturar** los **eventos** del ciclo de vida de la aplicación: * Utilizaremos la **clase** **abstracta** `**WidgetsBindingObserver**` como _**mixin**_ que nos permitirá observar los eventos del ciclo de vida y sobrescribir solo los métodos que nos interesen (el mixin no obliga a sobrescribir todos los métodos, al contrario que implementar una interfaz) * **Sobrescribiremos** el método `**didChangeAppLifecycleState(...)**` que se llamará cuando haya un cambio de estado en la aplicación. Ejemplo 1: Código[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-la-aplicacion#ejemplo-1-codigo) Copy import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State with WidgetsBindingObserver { @override void initState() { WidgetsBinding.instance.addObserver(this); super.initState(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } // WidgetsBindingObserver. // Called when the system puts the app in the background // or returns the app to the foreground. @override void didChangeAppLifecycleState(AppLifecycleState state) { print('State: ${state.name}'); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Flutter - Lifecycle'), ), body: Center(), ); } } **WidgetsBinding** és la **clase** **central** que actúa com el **vínculo** entre el framework Flutter y el motor Flutter subyacente. Es un **objeto** **singleton**, `WidgetsBinding.instance`y se encarga, entre otros de la supervisión del ciclo de vida, coordinar el renderizado correcto de los widgets, hacer llegar los eventos de entrada como gestos y toques a los widgets adecuados, accesibilidad, etc. Los **cambios** de **estado** los podemos observar en el **Logcat** cuando, por ejemplo realizamos las siguientes acciones: 1. Dejamos la aplicación en segundo plano: **inactive -> hidden -> pause** 2. Luego, volvemos a ella: **hidden -> inactive ->resumed** 3. Finalmente, la cerramos: **inactive ->** **hidden -> paused ->detached** > **Ejemplo de filtro Logcat:** > > Copy > > level:info message: State: package:com.example.ejemplo_flutter ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FIESvIZSTeokzL5AscWKH%252Fimage.png%3Falt%3Dmedia%26token%3De47f5644-7be8-40ec-811c-f2fedcc105fa&width=768&dpr=4&quality=100&sign=53b567fc&sv=2) ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-la-aplicacion#segunda-forma-usando-un-objeto-applifecyclelistener) Segunda forma: Usando un objeto **AppLifecycleListener** Podemos añadir un objeto de la clase `**AppLifecycleListener**` y así: * **Escuchar** **las transiciones** entre estados, sólo las que nos interesen, y también, * **Escuchar** siempre **cualquier** **cambio** de **estado**. ![](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/~gitbook/image?url=https%3A%2F%2F3645852152-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FTJQsPEhsPLjjuhB6XVoa%252Fuploads%252FCy480Hteyee1rlbjRAFE%252Fimage.png%3Falt%3Dmedia%26token%3Dcbacf0d6-d6b5-4ea7-96d3-4383f3969a25&width=768&dpr=4&quality=100&sign=451671eb&sv=2) [https://api.flutter.dev/flutter/widgets/AppLifecycleListener-class.html](https://api.flutter.dev/flutter/widgets/AppLifecycleListener-class.html) El **estado** **inicial** es el estado [AppLifecycleState.detached](https://api.flutter.dev/flutter/widgets/dart-ui/AppLifecycleState.html) . Las flechas describen transiciones de estado **válidas**. Las transiciones en **azul** son **transiciones** que solo ocurren en **iOS** y **Android**. Ejemplo 2: Código[](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-la-aplicacion#ejemplo-2-codigo) Copy import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State { late final AppLifecycleListener _myAppStateListener; @override void initState() { super.initState(); // Ahora indicamos qué transiciones queremos escuchar de forma individual _myAppStateListener = AppLifecycleListener( onDetach: () => print('Event: onDetach'), onShow: () => print('Event: onShow'), onHide: () => print('Event: onHide'), onInactive: () => print('Event: onInactive'), onPause: () => print('Event: onPause'), onRestart: () => print('Event: onRestart'), onResume: () => print('Event: onResume'), // Escuchamos también cualquier cambio de estado onStateChange: (state) => print('State: ${state.name}'), ); } @override void dispose() { _myAppStateListener.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Flutter - Lifecycle - AppLifecycleListener'), ), body: Center( child: Text('To observe states and lifecycle events: \n' 'Change device orientation, hide application, return back...\n ') ), ); } } [PreviousCiclo de Vida de los Widgets](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-los-widgets) [NextResponding to widget lifecycle events, Keys](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/responding-to-widget-lifecycle-events-keys) Last updated 11 months ago --- # Referencias | Dart **Guia oficial** [https://www.dartlang.org/guides/language/language-tour](https://www.dartlang.org/guides/language/language-tour) **Guía rápida:** [https://www.tutorialspoint.com/dart\_programming/dart\_programming\_quick\_guide.htm](https://www.tutorialspoint.com/dart_programming/dart_programming_quick_guide.htm) **Ejercicios:** [https://hackmd.io/@kuzmapetrovich/S1x90jWGP#Practice-Dart---exercises-for-beginners](https://hackmd.io/@kuzmapetrovich/S1x90jWGP#Practice-Dart---exercises-for-beginners) **Tutoriales** Dart en general: * [https://www.vogella.com/tutorials/Dart/article.html](https://www.vogella.com/tutorials/Dart/article.html) * [https://www.tutorialspoint.com/dart\_programming/](https://www.tutorialspoint.com/dart_programming/dart_programming_string.htm) Código asíncrono en Dart: [https://dart.academy/asynchrony-primer-for-dart-and-flutter/](https://dart.academy/asynchrony-primer-for-dart-and-flutter/) Explicación técnica de la "Event loop" interna de Dart: [https://dart.cn/articles/archive/event-loop](https://dart.cn/articles/archive/event-loop) [PreviousIntroducción](https://ecm-pmdm-flutter.gitbook.io/dart) [NextConceptos Básicos](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos) Last updated 1 year ago --- # Responding to widget lifecycle events, Keys | 1. Introducción a Flutter [https://docs.flutter.dev/development/ui/widgets-intro](https://docs.flutter.dev/development/ui/widgets-intro) [https://www.raywenderlich.com/22416843-unlocking-your-flutter-widgets-with-keys](https://www.raywenderlich.com/22416843-unlocking-your-flutter-widgets-with-keys) After calling [`createState()`](https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html#createState) on the `StatefulWidget`, the framework inserts the new state object into the tree and then calls [`initState()`](https://api.flutter.dev/flutter/widgets/State-class.html#initState) on the state object. A subclass of [`State`](https://api.flutter.dev/flutter/widgets/State-class.html) can override `initState` to do work that needs to happen just once. For example, override `initState` to configure animations or to subscribe to platform services. Implementations of `initState` are required to start by calling `super.initState`. When a state object is no longer needed, the framework calls [`dispose()`](https://api.flutter.dev/flutter/widgets/State-class.html#dispose) on the state object. Override the `dispose` function to do cleanup work. For example, override `dispose` to cancel timers or to unsubscribe from platform services. Implementations of`dispose` typically end by calling `super.dispose`. For more information, see [`State`](https://api.flutter.dev/flutter/widgets/State-class.html) . ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/responding-to-widget-lifecycle-events-keys#keys) Keys Use keys to control which widgets the framework matches up with other widgets when a widget rebuilds. By default, the framework matches widgets in the current and previous build according to their [`runtimeType`](https://api.flutter.dev/flutter/widgets/Widget-class.html#runtimeType) and the order in which they appear. **With keys, the framework requires that the two widgets have the same** [`**key**`](https://api.flutter.dev/flutter/foundation/Key-class.html) **as well as the same** `**runtimeType**`**.** **Keys are most useful in widgets that build many instances of the same type of widget**. For example, the i a `ShoppingList` widget, which builds just enough `ShoppingListItem` instances to fill its visible region: * Without keys, the first entry in the current build would always sync with the first entry in the previous build, even if, semantically, the first entry in the list just scrolled off screen and is no longer visible in the viewport. * By assigning each entry in the list a “semantic” key, the infinite list can be more efficient because the framework syncs entries with matching semantic keys and therefore similar (or identical) visual appearances. Moreover, **syncing the entries semantically means that state retained in stateful child widgets remains attached to the same semantic entry rather than the entry in the same numerical position in the viewport**. For more information, see the [`Key`](https://api.flutter.dev/flutter/foundation/Key-class.html) API. ### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/responding-to-widget-lifecycle-events-keys#global-keys) Types of keys There are two types of keys in Flutter: `GlobalKey`s and `LocalKey`s. * Local keys are unique only among siblings. * Global keys are globally unique across the entire widget hierarchy. #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/responding-to-widget-lifecycle-events-keys#the-different-types-of-localkeys-are) The different types of `LocalKey`s are: * _ValueKey_: A key that uses a simple value such as a String. * _ObjectKey_: A key that uses a more complex data format rather than a primitive data type like a String. * _UniqueKey_: A key that is unique only to itself. Use this type of key when you don't have any other data that makes a widget unique when using a `ValueKey` or an `ObjectKey`. #### [](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/responding-to-widget-lifecycle-events-keys#global-keys-1) Global keys Use global keys to uniquely identify child widgets. , unlike local keys which need only be unique among siblings. Because they are globally unique, a global key can be used to retrieve the state associated with a widget. For more information, see the [`GlobalKey`](https://api.flutter.dev/flutter/widgets/GlobalKey-class.html) API. [PreviousCiclo de vida de la aplicación](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/ciclo-de-vida-de-la-aplicacion) [NextEjemplo de uso de keys](https://ecm-pmdm-flutter.gitbook.io/1.-introduccion-a-flutter/4.-conceptos-fundamentales-en-flutter/ciclo-de-vida/responding-to-widget-lifecycle-events-keys/ejemplo-de-uso-de-keys) Last updated 11 months ago --- # Control de Flujo: Condiciones y Bucles | Dart En Dart podemos controlar el flujo de ejecución del programa con sentencias similares a C y Java: * **Condicionales** [https://dart.dev/language/branches](https://dart.dev/language/branches) * Selección simple: **if** (), **if**()...**else**... * Selección Múltiple: **switch** .. **case** * **Bucles** [https://dart.dev/language/loops](https://dart.dev/language/loops) * **while**, **do**..**while** * **for:** _for( ..; ..; )_ * **foreach:** _**for(.. in ..)**_ > Permiten el uso _continue_ y _break_ #### [](https://ecm-pmdm-flutter.gitbook.io/dart/control-de-flujo-condiciones-y-bucles#ejemplos) Ejemplos: Copy void main() { var year = 2010; var myName = 'Empar'; // IF if (year >= 2001) { // prints: 21st century print('21st century'); } else if (year >= 1901) { print('20th century'); } // SWITCH var fruit = 'tropical orange'; switch (fruit) { case 'apple': print('It\'s an apple!'); // break; // not necessary when case is not empty case 'banana': print('It\'s a banana!'); case 'orange': // empty case --> jumps next: 'mandarine' case 'mandarine': print('It\'s a type of orange!'); case String s when s.toLowerCase().contains('tropical'): // any kind of pattern print('It\'s a tropical fruit'); default: print('Unknown fruit'); } // SWITH EXPRESSION String myChar = '0'; String tipo = switch (myChar) { '/' || '*' || '+' || '-' => 'Es un operador', ',' || ';' || ':' => 'Es un signo de puntuación', _ => 'No está permitido', // also use: default instead of _ }; print(myChar + ' => ' + tipo); // PRINTS: '0 => No está permitido' // LOOPS // prints: [69] [109] [112] [97] [114] for (int c in myName.codeUnits) { print('[$c]'); } // prints: 1..12 for (int month = 1; month <= 12; month++) { print(month); } // prints: 2011..2015 while (year < 2016) { year += 1; print(year); } // prints: 2016..2022 do { print(++year); } while (year < 2022); } [Previousdynamic vs Object](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/dynamic-vs-object) [NextOperadores](https://ecm-pmdm-flutter.gitbook.io/dart/operadores) Last updated 2 hours ago --- # Conceptos Básicos | Dart ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos#punto-de-entrada) Punto de entrada Cada aplicación en Dart tiene un punto de entrada principal, la **función** `**main()**` > main se puede definir también con parámetros: `main(List args)` por si se necesita acceso a los argumentos desde la línea de comandos. Copy void main() { print('Hello World!!!'); } * Dart **no** **dispone** de los **modificadores**: `_**public**_`_,_ `_**private,**_` `_**protected**_`. * Se permite **definir** **código** a **nivel** **global (nivel superior)**, es decir, fuera de las clases: variables, funciones, getters y setters. * Por convención, Dart usa **sangría** (tabulación) **de 2** _**caracteres**_. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos#comentarios-en-el-codigo) Comentarios en el código * Los comentarios en Dart son como en otros lenguajes similares a C y Java. * Tenemos **3** **tipos** de comentarios: Copy // 1. Comentario de una línea /* 2. Comentario de varias líneas */ /// 3. Dcumentación API, y entre corchetes: [referencia a var/función ...] [PreviousReferencias](https://ecm-pmdm-flutter.gitbook.io/dart/referencias) [NextVariables](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/variables) Last updated 1 year ago --- # Resumen tipos de datos | Dart ![](https://ecm-pmdm-flutter.gitbook.io/dart/~gitbook/image?url=https%3A%2F%2F1551469701-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FsGv3FSfnl3pEE6ftH9Ys%252Fuploads%252FGY6MUi53rCbV7XBUbzYa%252Fimage.png%3Falt%3Dmedia%26token%3D2dcd2b20-03e4-4db7-a826-85074db43096&width=768&dpr=4&quality=100&sign=b94d51b8&sv=2) [PreviousTipos de datos básicos](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/tipos-de-datos-basicos) [Nextdynamic vs Object](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/dynamic-vs-object) Last updated 1 year ago --- # Dart Core Libraries | Dart Dart dispone de un rico conjunto de bibliotecas que proporcionan todo lo necesario para trabajar con: * **Colecciones** de objetos: `dart:collection` * **Cálculos** matemáticos: `dart:math`, * **Codificar**/**decodificar** diferentes representaciones de datos: JSON, UTF-8... `dart:convert` * etc, etc. Las bibliotecas que podemos utilizar en todas las plataformas son: * **dart:async** : permite la programación asíncrona, con clases como Future y Stream. * **dart:collection** : Colecciones que no aparecen en dart:core. * **dart: convert** : Conversiones entre tipos de datos. * **dart:core** : Tipos, colecciones, y funcionalidad básica para todo programa Dart (se importa de forma implícita). * **dart: developer** : Interacción con las herramientas de desarrolador como el _debugger_ y el _inspector_. * **dart:math** : Constantes y funciones matemáticas además del generador de números aleatorios. * **dart:typed\_data** : Porporciona listas para manejar de forma eficiente datos de tamaño fijo. (por ejemplo, enteros sin signo de 8 bytes): ByteData, ByteBuffer,... Documentación oficial: [https://dart.dev/guides/libraries](https://dart.dev/guides/libraries) [PreviousFunciones](https://ecm-pmdm-flutter.gitbook.io/dart/funciones) [NextClases](https://ecm-pmdm-flutter.gitbook.io/dart/clases) Last updated 2 days ago --- # Colecciones | Dart Dart proporciona **soporte** **nativo** (dart:core) para las **siguientes** **colecciones:** * List * Map * Set * Se pueden utilizar directamente puesto que la biblioteca `dart:core`, se importa implícitamente, * Para utilizar otras colecciones, como colas `Queue`, etc, hay que importar la biblioteca `dart:collection:` [`https://api.dart.dev/stable/dart-collection/dart-collection-library.html`](https://api.dart.dev/stable/dart-collection/dart-collection-library.html) [PreviousString](https://ecm-pmdm-flutter.gitbook.io/dart/string) [NextList](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list) Last updated 12 months ago --- # String | Dart **String** es el tipo de dato para representar una secuencia de caracteres en Dart (en formato UTF-16 (16-bit Unicode Transformation Format)). Las cadenas son **inmutables**. Podemos **crear cadenas** con: * **comillas dobles.** Ejemplo: "cadena" y también con * **comillas simples.** Ejemplo: 'cadena' ### [](https://ecm-pmdm-flutter.gitbook.io/dart/string#string-multi-linea) String Multi-línea Dart soporta **cadenas** **mult**\-**línea** con triple comilla (simple o doble): Copy main() { var message = """ Hi! Welcome to Programming Dart! """; print(message); // prints: Hi! // Welcome to Programming Dart! } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/string#concatenacion) Concatenación * Las cadenas (Strings), pueden construirse con el **operador +** * También funciona la concatenación en varias líneas. Copy var s1 = 'String ' + 'concatenation' " works even over line breaks."; print(s1); // "String concatenation works even over line breaks." ### [](https://ecm-pmdm-flutter.gitbook.io/dart/string#interpolacion-de-cadenas) Interpolación de cadenas * Podemos usar el valor de una expresión dentro de una cadena con: **$ { expressión }**. * Si la expresión es un identificador, no son necesarias las llaves: **{ }**. Dart usa por defecto el mètodo _toString()_ para devolver la representación en cadena de un objeto. Copy var s = 'string interpolation'; assert('Dart has $s, which is very handy.' == 'Dart has string interpolation, ' + 'which is very handy.'); // ok assert('That deserves all caps. ' + '${s.toUpperCase()} is very handy!' == 'That deserves all caps. ' + 'STRING INTERPOLATION is very handy!'); //ok ### [](https://ecm-pmdm-flutter.gitbook.io/dart/string#comparacion-de-cadenas) Comparación de cadenas * Dos cadenas son iguales si contienen la misma secuencia de caracteres. * Para **comparar** cadenas usaremos el operador **\==** ### [](https://ecm-pmdm-flutter.gitbook.io/dart/string#caracteres-unicode-32-bits) Caracteres Unicode 32-bits * Para insertar **caracteres Unicode de 32 bits** en una cadena UTF-16 usaremos una sintaxis especial (los llamados Runes) \\uXXXX) donde X es un dígito hexadecimal. Por ejemplo, ♥ se expresa: **\\u2665**. * Si tenemos menos o más de cuatro dígitos hexadecimals usaremos {}: Por ejemplo: 😆 seria: **\\u{1f600}** Al igual que en otros lenguajes similares a C, también podremos usar otras **secuencias** **de** **escape**, como **\\n** para insertar una nueva línea, **\\t** para insertar una tabulación, etc. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/string#propiedades) Propiedades En un String, podemos **consultar** las siguientes **propiedades** (de sólo lectura): * _**isEmpty**_: true si la cadena està vacía.. * _**length**_: longitud de todos los caracteres de la cadena. * _**codeUnits**_: devuelve una lista con los códigos UTF-16 de los caracteres de la cadena. Copy void main() { String mySentence = "Hello!"; var myEmptyString = ""; print(mySentence.isEmpty); // false print(myEmptyString.isEmpty); // true print(mySentence.length); // 6 print(myEmptyString.length); // 0 print(mySentence.codeUnits); // [72, 101, 108, 108, 111, 33] } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/string#metodos-para-manipular-strings) Métodos para manipular Strings Dart proporciona multitud de métodos para manejar cadenas: * toLowerCase(), * toUpperCase(), * trim(), * replaceAll(), * split(), * substring(), * ....... Más información: * [https://dart.dev/language/built-in-types#strings](https://dart.dev/language/built-in-types#strings) * [https://api.flutter.dev/flutter/dart-core/String-class.html](https://api.flutter.dev/flutter/dart-core/String-class.html) [PreviousOperadores](https://ecm-pmdm-flutter.gitbook.io/dart/operadores) [NextColecciones](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones) Last updated 2 hours ago --- # dynamic vs Object | Dart En Dart, `**dynamic**` y `**Object**` son dos tipos que podemos usar cuando no estamos seguros del tipo de una variable. Pero tienen algunas diferencias importantes: * `**dynamic**` no es realmente un tipo, sino que es una forma de **desactivar** **la** **comprobación** **de** **tipos**. `**dynamic**` Acepta **cualquier** **tipo** de valor incluido _null._ Cuando declaramos una variable como dynamic, le estamos indicando al analizador estático que confíe en nosotros y que no compruebe nada, por lo que **no lanzará ningún error** en su uso. * `**Object**` es el tipo de datos 'base' de todos los tipos de datos no nulos (Object? que accepta también null). Cuando definimos una variable como _Object,_ el analizador estático **lanzará** **una** **error** si se realizan operaciones no permitidas en _Object_, por lo que se tendrá que convertir al tipo deseado antes de su uso o **no compilará**. Source: [https://www.cloudhadoop.com/dart-dynamic-vs-object/](https://www.cloudhadoop.com/dart-dynamic-vs-object/) [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/dynamic-vs-object#ejemplos) Ejemplos ------------------------------------------------------------------------------------------------------- Las variables `**dynamic**` pueden ser asignadas a cualquier tipo de datos (y null) y estas variables se pueden asignar a cualquier otro tipo de variable. Copy void main() { //dynamic variable assigned with string dynamic name = "john"; // you can assign dynamic variable to any other variable // no static type checking! String fname = name; int number = name; // types not match --> Execution Error !! } Cuando declaramos una variable del tipo **Object**, podemos asignarle cualquier tipo de datos, pero deberemos realizar **casting** (typecase) cuando las asignamos a otro tipo de variable. Copy void main() { Object age = 25; int age1 = age as int; // static type check --> typecase before assigning! } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/dynamic-vs-object#valores-null) **Valores Null** Copy main() { dynamic str = null; // No error Object obj = null; // Compile time error !! Object? objnullable = null; // No error } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/dynamic-vs-object#acceso-a-metodos-y-propiedades) Acceso a métodos y propiedades Copy class Employee { printEmp() => print("Employee Object"); } void main() { dynamic a = new Employee(); Object b = new Employee(); a.printEmp(); // No error b.printEmp(); // Compile error } **Explicación del código:** * Cuando creas una instancia de la clase `**Employee**` con un tipo dinámico, puedes acceder a los métodos y propiedades. * En cambio, lo mismo no funciona para `**Object**`, los métodos y propiedades no son accesibles. [PreviousResumen tipos de datos](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/resumen-tipos-de-datos) [NextControl de Flujo: Condiciones y Bucles](https://ecm-pmdm-flutter.gitbook.io/dart/control-de-flujo-condiciones-y-bucles) Last updated 1 year ago --- # List | Dart Documentación oficial: [https://api.dart.dev/stable/dart-core/List-class.html](https://api.dart.dev/stable/dart-core/List-class.html) Dart, a diferencia de otros lenguajes, **no proporciona** _**arrays.**_ Dart representa los arrays en forma de **lista.** Una **lista** es una **secuencia** **ordenada** de objetos. La lista se puede **crear**: * Con un **tamaño** **fijo,** por lo que ya **no** **podrá** **cambiar** de **tamaño** en ejecución (daría error al añadir/quitar elementos). * Para que crezca **dinámicamente** su número de elementos. [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list#caracteristicas) **Características** ------------------------------------------------------------------------------------------------------ * Se pueden **recorrer** los elementos de la lista**,** puesto que son `_Iterable_`. * El **acceso** a los elementos de la lista se realiza a través de un **índice** entre corchetes: `**[ ]**`. * El **primer** **elemento** de la lista comienza con el **índice** **0**. * El índice del **último** **elemento** de la lista sería: **número** de **elementos de la lista - 1**. [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list#constructores) **Constructores** -------------------------------------------------------------------------------------------------- _List.empty(), List.filled(...), List.generate(..), List.of(..), List.unmodifiable(..), List.from(..)_ [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list#propiedades) **Propiedades** ---------------------------------------------------------------------------------------------- _first, last, length, isEmpty, isNotEmpty, iterator,...._ [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list#metodos) **Métodos** -------------------------------------------------------------------------------------- _add(...), clear(), contains(..), elementAt(..), remove(..), removeAt(..), ...._ [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list#ejemplos) **Ejemplos** ---------------------------------------------------------------------------------------- ### [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list#creacion-de-listas-de-tamano-variable) **Creación** de listas de **tamaño** **variable** Copy void main() { // growable lists List desserts = ['cookies', 'cupcakes', 'donuts', 'pie']; var oddNumbers = [1, 3, 5]; // dart infers: List var mixedList = [1, "Hello", 0.9]; // dart infers: List // adding more elements to lists desserts.add("ice-cream"); oddNumbers.add(7); print(desserts); // prints: [cookies, cupcakes, donuts, pie, ice-cream] print(oddNumbers); // prints: [1, 3, 5, 7] print(mixedList); // prints: [1, Hello, 0.9] } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list#creacion-de-listas-de-tamano-fijo) **Creación** de listas de **tamaño** **fijo** Copy void main() { // fixed size list List fixedList = List.filled(5, 0); // not growable list of 5 elements equal to 0 print(fixedList); // prints: [0, 0, 0, 0, 0] // fixedList.add(10); // error, list is not growable List unmodifiableList = List.unmodifiable([1, 2, 3]); // unmodifiableList[0] = 4; // error, list is not modifiable print(unmodifiableList); } // Console output: // [0, 0, 0, 0, 0] // [1, 2, 3] ### [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list#acceso-y-recorrido-de-los-elementos-de-la-lista) **Acceso** y **recorrido** de los elementos de la lista Copy void main() { List desserts = ['cookies', 'cupcakes', 'donuts', 'pie']; print('Element at index 0 = ${desserts[0]}'); // prints: cookies print('Element at index 1 = ${desserts.last}'); // prints: pie // change value of element at index 1 desserts[1] = 'ice-cream'; // insert element at index 2 desserts.insert(2,'orange juice'); // prints all the list (index based) print('\nDesserts: using for'); for(var i=0; i years = Set(); // empty Set, also: var years = {}; var names = {'empar', "joan"}; // inferred type: Set from Literals // Set from a List, 'red' will be inserted once Set colors = Set.of(['blue', 'red', 'yellow', 'red']); print('years = $years'); // prints: years = {} print('names = $names'); // names = {empar, joan} print('colors = $colors'); // colors = {blue, red, yellow} // adding elements years.add(2021); years.addAll([2022, 2022, 2023]); // from a list with repeated elements // years.add('hello'); // error: element must be int // removing names.remove('empar'); // removes 'empar' and returns true names.remove('anna'); // 'anna' is not in Set: nothing is done and returns false // clearing Set colors.clear(); print('------ After adding years, removing names and clear colors:'); print('years = $years'); // prints: years = {2021, 2022, 2023} print('names = $names'); // names = {joan} print('colors = $colors'); // colors = {} } \` [PreviousMap](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/map) [NextFunciones](https://ecm-pmdm-flutter.gitbook.io/dart/funciones) Last updated 2 days ago --- # Programación funcional | Dart Dart da un buen soporte a la programación funcional, similar a Kotlin. La programación funcional tiene un papel muy importante en Dart. En Dart todo son objetos, las funciones son también objetos y tienen un tipo: _Function_. Por tanto, podemos: * Asignar a una variable una función e invocarla * Pasar una función como argumento de otra función. Veamos con ejemplos los conceptos de **Lambdas, Higher-Order functions** y **Closures**. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/programacion-funcional#lambdas) Lambdas Una "Expresión lambda" es una función sin nombre, también se llama _**Función anónima**_ o simplemente _**Lambda.**_ Ejemplo: Copy // normal functions have a name int addition(int x, int y) { return x + y; } void main() { // 1. lambda expression (function is nameless): only has parameters and body //--> assign it to a variable (of type Function, or use var) Function addFunc = (int x, int y) { return x + y; }; // 2. lambda with shorthand syntax: Fat Arrow var subsFunc = (int x, int y) => x - y; // use addFunc print(addition(30,20)); // prints: 50 print(addFunc(2,3)); // prints: 5 print(subsFunc(5, 9)); // prints: -4 } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/programacion-funcional#higher-order-function) Higher-Order Function Una función de orden superior és aquella que: * Acepta una función como parámetro, o que * Retorna una función, o * Las dos cosas a la vez ### [](https://ecm-pmdm-flutter.gitbook.io/dart/programacion-funcional#lexical-closures) Lexical closures > **Lexical scope** (ámbito léxico): Dart es un lenguaje de ámbito léxico, es decir, el ámbito de las variables se determina de forma estática, por su disposición al código, siguiendo las { }. De modo que, desde los niveles más internos se puede acceder a todo lo que hay en los niveles superiores. Un Closure es una función especial. El closure puede acceder y modificar los valores de variables presentes en su ámbito léxico, incluso cuando se usa fuera de su ámbito original. (En Java 8, no está permitido, pero sí en otros lenguajes como Kotlin) Ejemplo: Copy // function that multiplies two numbers double multiply(double a, double b) => a * b; // Returns a closure (Function) that multiplies [value] to the function's argument [x] Function makeMultiplier(double value) { return (x) => multiply(value, x); // [value] can be reached outside lexical scope } void main(){ // assign function makeMultiplier to variables Function mult5 = makeMultiplier(5.0); // mult5 holds value = 5.0 Function mult10 = makeMultiplier(10.0); // mult10 holds value = 10.0 // mult5 and mult10 has access to 'value' that is out of main lexical scope print(mult5(10)); // prints 50 print(mult10(2)); // prints 20 } [PreviousExcepciones](https://ecm-pmdm-flutter.gitbook.io/dart/excepciones) [NextConcurrencia-Programación asíncrona](https://ecm-pmdm-flutter.gitbook.io/dart/concurrencia-programacion-asincrona) Last updated 2 days ago --- # Tipos de datos básicos | Dart En Dart, **todos los tipos de datos son objetos,** derivan de **Object**. * El valor por defecto es _**null**_ _para las variables_ _**nullable**__,_ * En cualquier otro caso, las variables se han de **iniciar** antes de su uso. Dart tiene los siguientes **tipos** **básicos**: Tipo Ejemplos _**int**_ Números enteros (64 bits) 1000 _**double**_ Números con decimales (64 bits) 3.14156 _**bool**_ Booleanos true / false _**String**_ Secuencias de caracteres 'Hello' + 'world' o también: "Hello" + 'World !!' > `int` and `double` derivan del tipo `**num**`. Una variable del tipo `num` puede contener cualquier número entero o double. > > ![](https://ecm-pmdm-flutter.gitbook.io/dart/~gitbook/image?url=https%3A%2F%2F1551469701-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FsGv3FSfnl3pEE6ftH9Ys%252Fuploads%252FJfs0Gsb5bVQLpmmXucvk%252Fimage.png%3Falt%3Dmedia%26token%3Da8c29151-0977-4b97-9cad-87efd6b0ce32&width=300&dpr=4&quality=100&sign=57c25456&sv=2) #### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/tipos-de-datos-basicos#ejemplos) Ejemplos: Copy void main() { // Number type: int int myInt = 10; // type int var myIntVar = 15; // int type inferred by compiler int myIntHex = 0xDDDDEAEA; // hex value // Number type: double double myDouble = 3.141516; double myDoubleExp = 0.31415e2; // exponential double value var myDoubleVar = 2.71828; // double type inferred by compiler // Strings String professorName = "Empar"; var schoolName = "CIP FP BATOI"; // String type inferred // Boolean bool isTrue = true; // By default value of nullable variables is null double? myNullDouble; // nullable variable // num type variables: may be assigned any number num myNumVar = 10; // int value myNumVar = 13.14; // double value // print in the console some of them: print(myInt); print(myIntVar); print(myDouble); print(professorName); print(myDoubleExp); print(isTrue); print(myNullDouble); print(myIntHex); print(myNumVar); } Console Output: Copy 10 15 3.141516 Empar 31.415 true null 3722308330 13.14 ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/tipos-de-datos-basicos#tipado-dinamico-dynamic) Tipado dinámico: _**dynamic**_ Si al declarar una variable utilizamos la palabra reservada `_dynamic_` en vez de `_var_`, la variable será de **tipado** **dinámico** y podrá **contener** **cualquier** **tipo** de datos en cualquier momento, incluido _**null.**_ A una variable dinámica se le puede asignar cualquier otro tipo de variable sin necesitar realizar la conversión explícita de tipos con el operador _as_. Copy void main() { dynamic myDynamicVar; myDynamicVar = "Hello"; // String print(myDynamicVar); // Hello myDynamicVar = 0.5; // double print(myDynamicVar); // 0.5 myDynamicVar = 2022; // int print(myDynamicVar); // 2022 myDynamicVar = true; // bool print(myDynamicVar); // true } _**Atención:**_ * _dynamic_ debe usarse con **cautela** (puesto que desactiva la comprobación de tipos) * Se **recomienda** siempre la **especificación** del **tipo** (o usar `_var_`) en la declaración de la variable. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/tipos-de-datos-basicos#conversiones-entre-tipos-de-datos-parsing-y-toxxx) Conversiones entre tipos de datos (_parsing y toXXX_) Copy void main() { // String -> int var one = int.parse('1'); assert(one == 1); // String -> double var onePointOne = double.parse('1.1'); assert(onePointOne == 1.1); // int -> String String oneAsString = 1.toString(); assert(oneAsString == '1'); // double -> String String piAsString = 3.14159.toStringAsFixed(2); assert(piAsString == '3.14'); // double -> int double x = 2.5984; int y = x.toInt(); assert(y == 2); } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/tipos-de-datos-basicos#comprobacion-de-tipo-operador-is) **Comprobación de tipo : Operador** `_**is**_` Para comprobar si una variable es instancia de otra clase usaremos el operador: `**is**` `(o` `**is!**``)` **Ejemplo**: El siguiente código muestra: "_myVar is of type SampleClass"_ ya que myVar es del tipo SampleClass: Copy class SampleClass { } main() { var myVar = new SampleClass(); // new is optional if (myVar is SampleClass) { print("myVar is of type SampleClass"); } } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/tipos-de-datos-basicos#casting-en-dart-operador-as) _**Casting**_ **en Dart: Operador** `_**as**_` Para realizar una **conversión** **explícita** (_**casting**_) usaremos el operador `**as**` **Ejemplo**: Convertimos la variable `emp` a tipo `Person` para acceder al campo `firstName`: Copy (emp as Person).firstName = 'Empar'; ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/tipos-de-datos-basicos#consultar-el-tipo-de-datos-de-una-variable-runtimetype) Consultar el tipo de datos de una variable_**:**_ `_**runtimeType**_` Podremos consultar el tipo de una variable durante la ejecución del programa con la propiedad _**runtimeType:**_ Copy void main() { var empar = 'EMPAR'; var number = 10.1; number = 1000; print(empar.runtimeType); // String print(number.runtimeType); // int, was the type of last value assigned bool myBoolean = false; print(miBooleana.runtimeType); // bool // dynamic variable dynamic myDynVar; myDynVar = "Empar"; print ("myDynVar=" + myDynVar + " y ahora es del Tipo: " + myDynVar.runtimeType.toString()); myDynVar = 12; print ("myDynVar=" + myDynVar.toString() + " y ahora es del Tipo: " + myDynVar.runtimeType.toString()); myDynVar = 20.33; print ("myDynVar=" + myDynVar.toString() + " y ahora es del Tipo: " + myDynVar.runtimeType.toString()); } [PreviousVariables](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/variables) [NextResumen tipos de datos](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/resumen-tipos-de-datos) Last updated 1 year ago --- # Funciones | Dart En Dart todo son objetos, incluidas las **funciones** que tienen su propio tipo: **Function**. Eso significa que podemos: * Pasar una función como parámetro a otra función, * Devolver una función desde otra función, * Asignar una función a una variable. Dart también permite declarar una función dentro de otra función. ![](https://ecm-pmdm-flutter.gitbook.io/dart/~gitbook/image?url=https%3A%2F%2F1551469701-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FsGv3FSfnl3pEE6ftH9Ys%252Fuploads%252FnVY1fseIEs6KEv9WmUeJ%252Fimage.png%3Falt%3Dmedia%26token%3Da1887424-b760-40e2-be65-a1936ab3b223&width=768&dpr=4&quality=100&sign=746741d7&sv=2) Todas las funciones (denominadas _métodos_ si están dentro de una clase) han de **devolver** un valor de un **tipo** o si no, se declaran _**void**_ y no hay _return._ * Se recomienda siempre declarar el tipo de dato devuelto. * Si se **omite** el **tipo** de **retorno** de la función y se **omite** el return se **devuelve** por defecto _**null**__._ * Las funciones que no pertenecen a ninguna clase son las llamadas _**top-level functions**__._ **Ejemplos**: Copy void main() { int total = add(5, 2); print("Total sum of 5 + 2 = $total"); // prints: Total sum of 5 + 2 = 7 printHello('Empar'); // prints: Hello Empar !! print("5 * 4 = ${mult(5, 4)}"); // prints: 5 * 4 = 20 print("-5 * 4 = ${mult(-5, 4)}"); // prints: -5 * 4 = null } int add(int a, int b) { return a + b; } void printHello(String name) { // no return type print('Hello $name !!'); } mult(int a, int b) { // return type omitted if (a>0 && b>0) return a * b; // returns null in othercase } [](https://ecm-pmdm-flutter.gitbook.io/dart/funciones#sintaxis-abreviada-de-funciones-notacion-arrow-greater-than) **Sintaxis abreviada de funciones: notación arrow** `**=>**` ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Si una función **sólo** **contiene** **una** **expressión** podemos utilizar una **notación** **abreviada**: `**=> ;**` > **Nota:** Sólo puede aparecer una expresión —no una sentencia— entre la flecha `**=>**` i el punto i coma (;). Es decir, por ejemplo, no podemos poner una sentencia `if`, pero sí una expresión condicional: `? :` . Por ejemplo, la función `add` del ejemplo anterior se puede escribir en una sola línea: Copy int add(int a, int b) => a + b; [](https://ecm-pmdm-flutter.gitbook.io/dart/funciones#funcion-como-argumento) **Función como argumento** ------------------------------------------------------------------------------------------------------------- Podemos pasar una función como argumento de otra función: Copy // function as argument void main() { int a = 5; int b = 4; print("$a + $b = ${calculate(a, b, add)}"); // prints: 5 + 4 = 9 print("$a * $b = ${calculate(a, b, mult)}"); // prints: 5 * 4 = 20 } int add(int a, int b) => a + b; int mult(int a, int b) => a * b; int calculate(int a, int b, Function doOperation) => doOperation(a, b); [](https://ecm-pmdm-flutter.gitbook.io/dart/funciones#parametros) Parámetros --------------------------------------------------------------------------------- En una función se pueden declarar cualquier número de **parámetros** **posicionales** **requeridos (**es **obligatorio** **especificarlos** **todos** en la llamada a la función) seguido de: 1. **Parámetros con nombre** (_named_) **o** 1. **Parámetros** **posicionales opcionales** _(optional positional)_, **Atención: NO puede haber a la vez parámetros del tipo (1) y tipo (2).** ### [](https://ecm-pmdm-flutter.gitbook.io/dart/funciones#parametros-con-nombre) Parámetros con nombre Permiten establecer el valor del **parámetro** **por** su **nombre** (muy conveniente cuando la función tiene muchos parámetros). > En Flutter, los constructores pueden llegar a ser bastante complejos así que se recomienda utilizar sólo parámetros con nombre. * Se declaran en la función entre `**{ }**`**después de los parámetros posicionales requeridos**. * Cuando se llama a la función, **especificaremos** el parámetro con su nombre y su valor con la **sintaxis**: (el orden no importa) `**nombreParametro: valor**` * Por **defecto**, son _**opcionales**_ a no ser que se especifiquen como `**required**`_._ * Se puede definir un **valor** por **defecto** con `**=**` (**obligatorio** si es opcional y no es _nullable_) **Ejemplo:** Copy void main() { print(add(5, d: 5)); // prints: 15 print(add(5, b: 10, d: 15)); // prints: 35 print(add(5, d: 20, c: 10, b:100)); // prints: 135 } // b is optional nullable optional named parameter, // c is optional named parameter with default value // d is required named parameter int add(int a, {int? b, int c = 5, required int d}) { if (b == null) return a + c + d; else return a + b + c + d; } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/funciones#parametros-posicionales-opcionales) Parámetros posicionales opcionales * Los parámetros posicionales que estén entre `**[ ]**` serán **opcionales**, se declaran **después de los parámetros posicionales requeridos.** * Se les puede asignar un **valor** por **defecto** con `**=**` (obligatorio si no es un parámetro _nullable_) **Ejemplo**: Copy void main() { print(add(1)); // prints: 21 print(add(1, 2)); // prints: 13 print(add(1, 2, 3)); // prints: 6 } int add(int x, [int? y, int z = 10]) { // y, z are optional positional parameters var total = x; total += y ?? 10; // if y!=null adds y otherwise adds 10 return total+=z; } [PreviousSet](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/set) [NextDart Core Libraries](https://ecm-pmdm-flutter.gitbook.io/dart/dart-core-libraries) Last updated 1 day ago --- # Variables | Dart Dart es un lenguaje de **tipado** **estático**, lo que significa que cada variable en Dart tiene un tipo que debe conocerse cuando se compila el código. El **tipo** de la variable **no** puede **cambiar** durante la ejecución del programa. C, Java, Swift y Kotlin también son de tipado estático. > Esto contrasta con lenguajes como Python y JavaScript, que son de _tipado dinámico_. Eso significa que las variables pueden contener diferentes tipos de datos cuando ejecuta el programa. No necesita saber el tipo cuando compila el código. Copy // Prints on Console the value of integer variable: 153 void main() { int length = 153; print(length); } Además, Dart realiza la **inferencia** **de** **tipos** cuando no se define de forma explícita el tipo de datos. Así, anteponiendo la palabra reservada `**var**` al nombre de variable, se le dice al compilador que debe determinar (inferir) el tipo de variable a partir del valor que se le asigne. Copy // Prints on Console the value of infered double variable: 3.141516 void main() { var pi = 3.141516; print(pi); } **Atención** al definir los nombres de identificadores: * Deben ser **únicos**. * Los identificadores **no** **pueden** **contener** **palabras** **reservadas**. * **No** están **permitidos** los **números** al **inicio** ni los caracteres en blanco o especiales, a excepción del guion bajo “\_” y el símbolo de dólar “$”. * Los identificadores **diferencian** entre **mayúsculas** y las **minúsculas**. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/variables#modificadores) Modificadores Las variables pueden tener los siguientes modificadores: * `**final**`: Una variable final se puede inicializar solo una vez, no se puede reasignar, debe inicializarse antes de utilizarse. * `**const**` - Una variable const es una constante en tiempo de compilación. Una constante es implicitamente `final`. * `**static**`: las variables estáticas están disponibles en la clase en lugar de la instancia. Un _**"literal"**_ és una constante en tiempo de compilación: un número, una expresión que se evalúa a número, _null_, _true/false_ o una cadena. #### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/variables#ejemplo) Ejemplo: Copy void main() { const String hello = "Hello World!"; // constant String const upperLimit = 10; // infered integer constant final age; // final variable print(hello); // prints constant String value: Hello World print(upperLimit); // prints infered constant int value: 10 age = 25; // final variable assigned to int value: 25 // age = 30; // reports error: as age variable is already assigned print('age = ' + age.toString()); // prints 25 } **Atención**: * Si no hay intención de cambiar el valor de una variable s_e_ ha de usar el **modificador** `**final**` o `**const**`. * El valor de una variable `const` se determina en **tiempo de compilación** y **no se puede cambiar** en tiempo de ejecución (ni tampoco el valor de sus atributos ) es **inmutable** * El valor de una variable `**final**` **no se puede cambiar** en tiempo de ejecución (pero sí sus atributos, si apunta a objeto) ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/variables#null-safety) Null-Safety * Dart es "**null** **safe**". * Los valores _**null**_ son usualmente causa de múltiples errores durante la ejecución de los programas. * Por ello, en Dart por defecto es **obligatorio** que **todas** las variables han de estar **inicializadas** a algún valor antes de poder utilizarlas o se produce un error de **compilación**. Copy void main() { String cadena; // variable sin inicializar print(cadena); } El ejemplo anterior da un **Error de compilación:** Error compiling to JavaScript: Info: Compiling with sound null safety Warning: Interpreting this as package URI, 'package:dartpad\_sample/main.dart'. lib/main.dart:3:9: Error: Non-nullable variable 'cadena' must be assigned before it can be used. print(cadena); ^^^^^^ Error: Compilation failed. * Para **declarar** que una variable pueda tener un valor `null` se añadirá `**?**` al tipo de dato. **Ejemplo:** Copy main() { int? i; print(i); // prints null } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/variables#variables-private) Variables private En Dart no existe el modificador _private_. Si queremos **indicar** que una **variable** (o método) sólo se pueda utilizar en su biblioteca (cada fichero dart es una biblioteca o _library_ ) se **prefija** con **guión** **bajo**: `int _myPrivateVariable; //visible sólo en este fichero dart` [PreviousConceptos Básicos](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos) [NextTipos de datos básicos](https://ecm-pmdm-flutter.gitbook.io/dart/conceptos-basicos/tipos-de-datos-basicos) Last updated 2 days ago --- # Packages and Libraries | Dart [![Logo](https://ecm-pmdm-flutter.gitbook.io/dart/~gitbook/image?url=https%3A%2F%2Fmiro.medium.com%2Fv2%2Fresize%3Afill%3A304%3A304%2F10fd5c419ac61637245384e7099e131627900034828f4f386bdaa47a74eae156&width=20&dpr=4&quality=100&sign=d77d307f&sv=2)🎯 Dart (DartLang) Introduction: Packages and LibrariesMedium](https://medium.com/run-dart/dart-dartlang-introduction-packages-and-libraries-c2fd75cf5606) [![Logo](https://ecm-pmdm-flutter.gitbook.io/dart/~gitbook/image?url=https%3A%2F%2Fdart.dev%2Fassets%2Fimg%2Ftouch-icon-iphone-retina.png&width=20&dpr=4&quality=100&sign=cf9193f5&sv=2)How to use packagesdart\_lang](https://dart.dev/guides/packages) [PreviousFutures, async/ await](https://ecm-pmdm-flutter.gitbook.io/dart/concurrencia-programacion-asincrona/futures-async-await) [NextGuia para escribir código Dart standard, claro y efectivo](https://ecm-pmdm-flutter.gitbook.io/dart/guia-para-escribir-codigo-dart-standard-claro-y-efectivo) Last updated 3 years ago --- # Concurrencia-Programación asíncrona | Dart Dart es un lenguaje _**single-threaded.**_ Esto no quiere decir que Dart no pueda ejecutar código en paralelo. Cuando iniciamos una aplicación Dart (con o sin Flutter), el _runtime_ de Dart la arranca dentro de un nuevo thread aislado: _**main isolate.**_ El runtime de Dart modela los threads como _**isolates**_, es decir, completamente aislados unos de otros, no comparten memoria, lo cual evita la necesidad de bloquear la memoria para evitar las _race conditions.._ Para operaciones computacionalmente largas, se pueden lanzar varios isolates y así evitar bloquear el main isolate del programa. El código dentro de cada isolate individual es single-threaded, lo cual significa que sólo una operación se ejecuta a la vez. En el siguiente vídeo se explica cómo ejecutar código en un nuevo _isolate_: [https://www.youtube.com/watch?v=PPwJ75vqP\_s](https://www.youtube.com/watch?v=PPwJ75vqP_s) (2 mins) **Ejemplo de función síncrona**: (mientras se está ejecutando y no termine, no se pueden procesar clics y otros eventos/tareas en el isolate) Copy void syncFuncExample() { var count = 0; for (int i = 0; i < 1000000; i++) { count++; } } Entonces, ¿cómo **evitamos** **bloquear** el _isolate_ actual mientras esperamos que las operaciones de cierta duración acaben? (I/O: network, BD, files,..). Aquí es donde entran en acción los patrones de la **programación asíncrona**. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/concurrencia-programacion-asincrona#estructura-de-un-isolate) Estructura de un _isolate_ Dart implementa el siguiente modelo asíncrono (event-loop) de forma que el programa es capaz de manejar eventos que ocurren de forma no predecible pero sin bloquear los eventos de usuario (UI responsive) ![](https://ecm-pmdm-flutter.gitbook.io/dart/~gitbook/image?url=https%3A%2F%2F1551469701-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FsGv3FSfnl3pEE6ftH9Ys%252Fuploads%252FQT2zYppnU1XqqpIfQNm5%252Fimage.png%3Falt%3Dmedia%26token%3D2a56e9b7-67c6-4e80-90e6-0655524ae059&width=300&dpr=4&quality=100&sign=9a9a8884&sv=2) **Event-loop**: La aplicación pasa la mayor parte del tiempo ejecutando las tareas de cada cola. Si no hay nada urgente, se ejecutan tareas como el garbage-collector. **Microtasks**: Son tareas de corta duración con más prioridad que los eventos. **Events**: Se añadirán eventos a la cola para que puedan ser ejecutados debido a: interacciones del usuario (clicks, teclas, gestos,..), I/O desde almacenamiento local o desde la red, Timers, Futures, Streams. > En Flutter, se utiliza la programación asíncrona que permite mantener la UI atenta a las acciones del usuario mientras se completan las tareas de cierta duración. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/concurrencia-programacion-asincrona#conceptos-basicos) Conceptos básicos * **Operación síncrona**: operación que bloquea a otras operaciones hasta termina de ejecutarse. * **Función síncrona:** función que sólo realiza operaciones síncronas. * **Operación asíncrona:** Una vez iniciada, la operación asíncrona permite que otras operaciones se realizen antes de que ésta termine. * **Función asíncrona:** realiza, al menos, una operación asíncrona y puede realizar también otras operaciones síncronas. [PreviousProgramación funcional](https://ecm-pmdm-flutter.gitbook.io/dart/programacion-funcional) [NextFutures, async/ await](https://ecm-pmdm-flutter.gitbook.io/dart/concurrencia-programacion-asincrona/futures-async-await) Last updated 1 year ago --- # Map | Dart Documentación oficial: [https://api.dart.dev/stable/dart-core/Map-class.html](https://api.dart.dev/stable/dart-core/Map-class.html) Cuando necesitamos una estructura para guardar **pares** **clave-valor**, la clase **Map** es una buena elección. Un Map es una **colección** de pares **clave-valor** donde obtenemos el valor a partir de la clave (diccionario). Dart proporciona soporte nativo para Maps. Un Map en Dart es **similar** a los diccionarios de Swift o maps de Kotlin o **Java**. [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/map#caracteristicas) **Características** ----------------------------------------------------------------------------------------------------- * Un Map se puede **iterar**. Cada elemento se dice que es un par clave-valor. * Tanto la **clave** como el **valor** pueden ser de **cualquier** **tipo**. * La **clave** debe ser **única**, pero el valor puede repetirse. * Para **acceder** a un valor del Map debemos proporcionar la clave. Si la clave no se encuentra devuelve un valor `**null**`. * Se puede **cambiar** el valor para una clave existente. * Se pueden **añadir** dinámicamente más elementos clave-valor. [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/map#creacion-de-maps) **Creación de Maps** ------------------------------------------------------------------------------------------------------- ### [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/map#mediante-literales) Mediante Literales El map se declara entre `**{ }**` y `**,**` para separar los pares clave-valor. Copy // Map con clave String y valor int main() { Map calories = { 'cake': 550, 'donuts': 145, 'cookies': 75, }; print(calories); // prints: {cake: 550, donuts: 145, cookies: 75} } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/map#mediante-el-constructor) Mediante el constructor Copy //Map con clave String y valor String main() { Map loginInfo = Map(); // empty Map of print(loginInfo); // prints: {} } [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/map#gestion-de-los-elementos-del-map) **Gestión de los elementos del Map** --------------------------------------------------------------------------------------------------------------------------------------- Utilizamos los `**[ ]**` y dentro escribimos la clave. Copy main() { Map loginCodes = Map(); // equivale a poner el literal: {} loginCodes['empar'] = 1234; loginCodes['pep'] = 4321; //loginCodes['joan'] = '5467'; // error: value must be int not a String print(loginCodes); // prints: {empar: 1234, pep: 4321} print(loginCodes["empar"]); // prints: 1234 print(loginCodes['joan']); // prints: null (key 'joan' not found) Map calories = {'cake': 550, 'donuts': 145, 'cookies': 75, }; print(calories); // prints: {cake: 550, donuts: 145, cookies: 75} calories['cake'] = 334; // value of 'cake' is updated print(calories['cake']); // prints: 334 (instead of old value: 550) } [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/map#propiedades) **Propiedades** --------------------------------------------------------------------------------------------- * **keys**: devuelve un Iterable con las claves. * **values**: devuelve un Iterable con los valores. * **length**: devuelve el número de elementos del Map. * **otras propiedades**: isEmpty, isNotEmpty, entries, .... [](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/map#metodos) **Métodos** ------------------------------------------------------------------------------------- clear(), addAll(..), remove(..), containsKey(..), containsValue(...),..... [PreviousList](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/list) [NextSet](https://ecm-pmdm-flutter.gitbook.io/dart/colecciones/set) Last updated 2 days ago --- # Operadores | Dart Copy var miVar = 35; **Tipo de operador** **Nombre** **Ejemplo** **Resultado** **Aritmético** Suma **+** `miVar + 2;` 37 Resta **\-** `miVar - 2;` 33 Multiplicación **\*** `miVar * 3;` 105 División **/** `miVar / 7;` 5 Resto división **%** `miVar%3;` 2 Divide y retorna un resultado entero **~/** `miVar ~/ 7`; 11 Asigna suma **+=** `miVar += 6;` 41 Asigna resta **\-=** `miVar -= 7;` 28 Asigna producto **\*=** `miVar *= 2;` 70 Asigna división **/=** `miVar /= 7;` 5 Asigna resto **%=** `miVar %= 3;` 2 **De igualdad y relacionales** Es igual **\==** `miVar == 35;` true No es igual **!=** `miVar != 44;` true Menor que **<** `miVar < 44;` true Menor o igual que **<=** `miVar <= 35`; true Mayor que **\>** `miVar > 35` false Mayor o igual que **\>=** `miVar >=35;` true **Incremento y Decremento** Decrementa **\--** `miVar--`; 34 Incrementa **++** `++miVar; miVar++;` 36 **Lógicos** y **&&** `(41 < 42) && (42 < 43`) true o **||** `(41 < 42) || (42 > 43)` true Negación **!** `!(miVar >30)` false **Condicional** If-else **? :** `miVar < 34 ? 15 : 10;` 10 `miVar > 34 ? 15 : 10;` 15 **Operadores Nullable** Verificar valor y **asignar si no es Null**. **??** `var z = miVar ?? 9`; 35 **??** `int? n;` `n = 10;` `n = null;` `int z = n ?? 14;` \--> si es null se asigna valor alternativo proporcionado 14 **null-aware operator:** necesario en el acceso a atributos de tipos de **objetos** **nullable**. **?.** `Person``**?**` `p;` `print(p``**?.**``name)` null **?.** `Person``**?**` `p = Person("Empar");` `print(p``**?.**``name)` "Empar" **Bang operator:** Indica al compilador de Dart que **confíe**, que la variable, aunque sea de tipo _nullable_, tendrá **seguro un valor no nulo**. (hace casting de la variable al tipo no nulo) **!** Copy void main() { int? value; //.... printValue(value!); } void printValue(int value) => print(value); Usando !, podremos compilar y ejecutarlo, pero como value es null, dará un **error** en tiempo de ejecución al llamar a la función printValue (que no acepta null. **Notación Cascade** [(more info...)](https://dart.dev/guides/language/language-tour#cascade-notation) Permite realizar una **secuencia** de **operaciones** sobre el mismo **objeto** sin tener que usar la variable cada vez. (por ejemplo, para asignar atributos, llamar a métodos,..) **..** **o** **?..** Copy var paint = Paint() ..color = Colors.black ..strokeCap = StrokeCap.round ..strokeWidth = 5.0; // equivale a var paint = Paint(); paint.color = Colors.black; paint.strokeCap = StrokeCap.round; paint.strokeWidth = 5.0; [PreviousControl de Flujo: Condiciones y Bucles](https://ecm-pmdm-flutter.gitbook.io/dart/control-de-flujo-condiciones-y-bucles) [NextString](https://ecm-pmdm-flutter.gitbook.io/dart/string) Last updated 12 months ago --- # Funciones | Dart Ejercicio 1: Función suma lista[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/funciones#ejercicio-1-funcion-suma-lista) Escribe una función que tome como argumento una lista de valores double (`List`) y devuelva la suma de todos los valores de la lista. En la definición de la funcion, declara el parámetro con nombre. Desde la función principal, main(), llama a la función anterior con diferentes listas e imprime la lista y el resultado de la función. Por ejemplo, para las listas \[ \], \[5, 7\] y \[4, 3, 2, 1\] la salida sería: Copy [] --> Total suma = 0 [5, 7] --> Total suma = 12 [4, 3, 2, 1] --> Total suma = 10 Ejercicio 2: Comida para llevar utilizando funciones[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/funciones#ejercicio-2-comida-para-llevar-utilizando-funciones) El siguiente programa permite calcular el precio total de un pedido de comida para llevar: Copy void main() { const takeawayPrices = { 'Bajoques Farcides': 5.5, 'Olleta Alcoiana': 6.75, 'Paella Valenciana': 4.75, }; const order = [\ 'Bajoques Farcides',\ 'Olleta Alcoiana',\ ]; var total = 0.0; for (var item in order) { final price = takeawayPrices[item]; if (price != null) { total += price; } } print('Pedido: $order - Precio total: $total Euros'); } **Modifica** el programa anterior de forma que definas una función que tome como argumento un pedido y devuelva el precio total del mismo. El parámetro de la función se definirá con nombre. **Verifica** el correcto funcionamiento de la función con diferentes pedidos, también con pedidos que incluyan comidas que no están disponibles. Por ejemplo, la salida del programa con los datos del programa anterior sería: Copy Pedido: [Bajoques Farcides, Olleta Alcoiana] - Precio total: 12.25 Euros [PreviousColecciones](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/colecciones) [NextClases](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases) Last updated 1 year ago --- # Exceptions | Dart Ejercicio 1: Validación de e-mail[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/exceptions#ejercicio-1-validacion-de-e-mail) Crea una clase llamada **Email** que reciba como argumento en su constructor una cadena que represente un email. * Esta clase comprobará que se trata de un **email** **válido**. * Deberá lanzar una **excepción** del tipo `FormatException` ( con el mensaje adecuado) en los siguientes casos: * Cuando la cadena email está **vacía**, * Cuando la cadena email no contiene el carácter **@** * Sobrescribe el método `toString()` para que devuelva el email. Una vez terminada la implementación de la clase, **comprueba** que funciona correctamente con el siguiente código: Copy void main() { try { print(EmailAddress('myEmail@empar.dam')); print(EmailAddress('cipfpbatoi.es')); print(EmailAddress('')); } on FormatException catch (e) { print(e); } // Salida esperada: // myEmail@empar.dam // FormatException: cipfpbatoi.es no es una dirección de mail válida. // Ha de contener el carácter @ } **Mejora:** * **Añade** 2 o más restricciones adicionales al email. Por ejemplo: que incluya números u otro carácter, límite a la longitud, ... * Realiza el **lanzamiento** y la **captura** de las nuevas excepciones. * **Comprueba** con varios ejemplos de email no válidos que se lanzan y se capturan las nuevas excepciones. [PreviousClases](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases) [NextProgramación asíncrona](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-asincrona) Last updated 1 year ago --- # Programación asíncrona | Dart Ejercicio 1: Temporizador[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-asincrona#ejercicio-1-temporizador) Implementa una función llamada `temporizador` que tome como argumento un número entero llamado `num`. * La función mostrará en pantalla todos los números desde `num` hasta `0` con una pausa de 1 segundo entre cada número. * Utiliza adecuadamente: `Future`s, `async` y `await` Implementa main(): * **Llama** a la función implementada para **verificar** que funciona de la forma esperada. * main() imprimirá "Fin del Temporizador" cuando haya terminado la cuenta atrás. [PreviousExceptions](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/exceptions) Last updated 3 years ago --- # Guia para escribir código Dart standard, claro y efectivo | Dart Guía oficial: [https://dart.dev/guides/language/effective-dart#summary-of-all-rules](https://dart.dev/guides/language/effective-dart#summary-of-all-rules) En general: sé **conciso** y **breve**: si hay varias formas de solucionar un problema, escoge la más corta y la más clara. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/guia-para-escribir-codigo-dart-standard-claro-y-efectivo#convenciones-de-nombres) **Convenciones** **de** **nombres**: * Para nombrar las clases usaremos _UpperCamelCase_, ejemplo: `SliderMenu(), HttpRequest`…​ * Para nombrar fichero, package, directorio y library utilizaremos nombres en _lowercase\_with\_underscores_, ejemplos: `file_system.dart, slider_menu.dart, …​` * Los alias en imports siempre _lowercase_, ejemplo: `import 'dart.math' as math` * Los identificadores y constantes siempre en lowerCamelCase: `var item;` `HttpRequest httpRequest` ### [](https://ecm-pmdm-flutter.gitbook.io/dart/guia-para-escribir-codigo-dart-standard-claro-y-efectivo#lo-que-evitaremos) **Lo que EVITAREMOS:** MAL BIEN Capitalizar acrónimos `HTTPConnection` `IOStream` `HttpConnectionInfo` `IoStream` Abreviación como palabra `int? ID` `int? Id` Usar la barra baja al inicio del nombre (`_example`) En cualquier caso Sólo cuando sea un miembro privado. Usar una letra como prefijo de tipo `kDefaultTimeout` `defaultTimeout` Capitalizar las constantes y las enumeraciones `const int MAX_ITEMS = 10;` `enum MyColors { RED, AMBER, GREEN,}` Usar siempre lowerCamelCase: `const int maxItems = 10;` `enum MyColors { red, amber, green,}` ### [](https://ecm-pmdm-flutter.gitbook.io/dart/guia-para-escribir-codigo-dart-standard-claro-y-efectivo#orden-de-imports) Orden de _imports_ * imports de Dart siempre delante * imports de package antes de los import relativos * import de package externos antes que otros imports * especificar exports en una seccion separada después de todos los imports * ordenar cada subsección alfabéticamente Copy import 'dart:async'; import 'dart:html'; import 'package:bar/bar.dart'; import 'package:foo/foo.dart'; import 'package:my_package/util.dart'; import 'util.dart'; // relative to our project export 'src/error.dart'; ### [](https://ecm-pmdm-flutter.gitbook.io/dart/guia-para-escribir-codigo-dart-standard-claro-y-efectivo#formato) **Formato** * Dart proporciona el formato automático con la herramienta: _dartfm_. * Evitar líneas de más de 80 caracteres. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/guia-para-escribir-codigo-dart-standard-claro-y-efectivo#documentacion) Documentación * Usa // para los comentarios que se escriben como frases de texto normales. Copy // This is a simple comment. if (_chunks.isEmpty) return false; * Usa '///' para documentar miembros y tipos. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/guia-para-escribir-codigo-dart-standard-claro-y-efectivo#como-comprobar-automaticamente-si-no-cumplimos-las-convenciones-de-codigo) **¿Cómo comprobar automáticamente si no cumplimos las convenciones de código?** * Podemos forzar que el Dart Linter compruebe si el código sigue las guías de estilo estándar añadiendo lo siguiente: Copy include: package:pedantic/analysis_options.1.9.0.yaml * Simplemente crea un fichero '`analysis_options.yaml'` en el directorio principal del proyecto que contenga todas tus reglas. [PreviousPackages and Libraries](https://ecm-pmdm-flutter.gitbook.io/dart/packages-and-libraries) [NextConceptos básicos](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/conceptos-basicos) Last updated 2 years ago --- # Colecciones | Dart Ejercicio 1: List - Suma valores[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/colecciones#ejercicio-1-list-suma-valores) Dada una lista de valores enteros: `[10, 3, 25, 17, 12, 45]` Escribe un programa que calcule la **suma** de todos los valores de la lista e imprima la salida con el siguiente **formato**: `10 + 3 + 25 + 17 + 12 + 45 = 112` **Verifica** que el programa funciona correctamente cuando cambian los valores de la lista Ejercicio 2: Set - Diferencia simétrica de conjuntos[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/colecciones#ejercicio-2-set-diferencia-simetrica-de-conjuntos) Dados dos conjuntos de números enteros (Set), escribe un programa que obtenga un nuevo conjunto resultado de la **diferencia** **simétrica** de ambos conjuntos. Utiliza los métodos de clase Set (_union, difference, intersection)_ para realizar las operaciones con los conjuntos. _\--> La diferencia simétrica de A y B es el conjunto que contiene todos los elementos de A y de B salvo los elementos que pertenecen a ambos conjuntos. (_[_https://es.wikipedia.org/wiki/Diferencia\_simétrica_](https://es.wikipedia.org/wiki/Diferencia_sim%C3%A9trica) _)_ Luego, muestra también la **suma** de todos los elementos del conjunto resultado. Por ejemplo, para los siguientes conjuntos: Copy Set a = {3, 7, 1, 10}; Set b = {2, 1, 7, 5}; El programa debe imprimir: Copy Diferencia simétrica de {3, 7, 1, 10} y {2, 1, 7, 5} es: {3, 10, 2, 5} 3 + 10 + 2 + 5 = 20 Ejercicio 3: Map - Comida Para llevar[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/colecciones#ejercicio-3-map-comida-para-llevar) Dado el siguiente Map correspondiente a precios de comida para llevar: Copy const takeawayPrices = { 'Bajoques Farcides': 5.5, 'Olleta Alcoiana': 6.75, 'Paella Valenciana': 4.75, }; Escribe un programa que calcule el **precio** **total** de un pedido concreto. Por ejemplo, si tenemos una lista con el siguiente pedido: Copy const order = ['Bajoques Farcides', 'Olleta Alcoiana']; El programa deberá imprimir: Copy Pedido: [Bajoques Farcides, Olleta Alcoiana] TOTAL: 12.25 Euros **Atención**: Si en el pedido hay comidas que no están el menu, deberá avisar con un mensaje: Copy Pedido: [Bajoques Farcides, Olleta Alcoiana, Arròs del Senyoret] Atención: Arròs del Senyoret no está en el menú TOTAL: 12.25 Euros Ejercicio 4: Valoración de tiendas[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/colecciones#ejercicio-4-valoracion-de-tiendas) Dada la siguiente lista de tiendas: Copy var shops = [\ {\ 'name': 'Pizzeria Ma Casa',\ 'type': 'Restaurante',\ 'ratings': [4.0, 3.0, 4.5],\ },\ {\ 'name': 'Todo Bombillas',\ 'type': 'Iluminación',\ 'ratings': [5.0, 4.5, 3.5],\ },\ {\ 'name': 'Sport & Family',\ 'type': 'Deporte',\ 'ratings': [3.5, 4.0, 4.0],\ },\ ]; Escribe un programa que calcule la **valoración** media de cada tienda y la **añada** como un nuevo par clave-valor `'averageRating': averageRating` para esa tienda (con sólo un decimal). **Imprime** también todos los datos de esa tienda. Utiliza el siguiente código como punto de partida: Copy for (var shop in shops) { final ratings = shop['ratings'] as List; // TODO: calculate here the average rating (1 decimal point) shop['averageRating'] = averageRating; // TODO: print all shop info } La **salida** debería ser: Copy {name: Pizzeria Ma Casa, type: Restaurante, ratings: [4, 3, 4.5], averageRating: 3.8} {name: Todo Bombillas, type: Iluminación, ratings: [5, 4.5, 3.5], averageRating: 4.3} {name: Sport & Family, type: Deporte, ratings: [3.5, 4, 4], averageRating: 3.8} [PreviousProgramación básica](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-basica) [NextFunciones](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/funciones) Last updated 2 years ago --- # Excepciones | Dart [https://dart.dev/language/error-handling](https://dart.dev/language/error-handling) En Dart, podemos capturar y lanzar excepciones (_**exceptions**_). > Una excepción es un error que indica que ha ocurrido algo inesperado. Dart tiene una **jerarquía** de herencia de excepciones (similar a la de Java). La jerarquía permite capturar tipos de errores de manera granular, yendo de lo más específico a lo más general. Copy Object └─ Throwable (interfaz) ├─ Exception (interfaz) │ ├─ IOException │ │ ├─ FileSystemException │ │ ├─ SocketException │ │ └─ HttpException │ ├─ FormatException │ ├─ TimeoutException │ └─ ... (y muchas otras) │ └─ Error (clase) ├─ ArgumentError ├─ StateError ├─ TypeError ├─ RangeError └─ ... (y muchas otras) Las `Exception` son errores esperados que deberemos manejar, y los `Error` son señales de que tu código tiene un bug que necesita ser corregido. * A diferencia de Java, todas las excepciones son **unchecked** y los **métodos** **no** estan **obligados** ni a **declarar** qué excepciones lanzan **ni** a **capturar** ninguna excepción. * **Si una excepción no se captura no hay oportunidad para recuperarse del error, el hilo actual de ejecución (isolate) se suspende y el programa termina anómalamente**. * En Dart **se puede lanzar cualquier tipo de objeto no-nulo como excepción**, no sólo el tipo Exception y Error: * **Exception**: La usaremos cuando la intención es capturarla e informar al usuario para intentar recuperarse del error: FormatException, IOException,... * **Error**: Son errores no controlados y de los que es difícil recuperarse como index-out-of-range (error en la lógica) , out-of-memory...: IndexError, OutOfMemoryError,... * Podemos definir nuestros propios tipos de Exception/Error. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/excepciones#captura-de-excepciones-try-..-on-..-catch-..-finally) Captura de excepciones: try .. on .. catch .. finally Dart recomienda ser específico en el tipo de excepción que se captura (no usar solo Exception) y así poder dar información del tipo concreto de error. Para capturar las excepciones podemos usar **solo** `**on**` o **solo** `**catch**` o **ambos** (**on** ... **catch(e))**: * Usaremos `**on**` `` si solo queremos especificar el **tipo** de **excepción**. * Usaremos `**catch(..)**` cuando necesitemos el objeto _exception_ para tratarla. Podemos especificar `catch` con un parámetro: `catch(e)` o con dos parámetros: `catch(e, s)`. El primero es el objeto _**exception**_ que fue lanzado y el segundo parámetro es el _**stacktrace**__._ Podremos capturar más de un tipo de excepción con **múltiples bloques** `**on/catch**`. El primer bloque catch que coincida con el tipo del objeto exception lanzado será el que tratará la excepción. Si el bloque `**catch**` **no** **especifica** el tipo de excepción (on ` list.length - 1) { throw RangeError("Attention->index 3 out of list"); } } catch (e) { // general exception print('$e'); // prints: RangeError: Attention->index 3 out of list } try { if (list[2] > 2) { throw "${list[2]} must be a value <=2"; // error object is of type String } } catch (e) { // general exception print('$e'); // prints: 3 must be a value <=2 } } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/excepciones#custom-exception) Custom Exception En Dart, nos crearmos nuestras excepciones **implementando** la clase Exception donde podremos sobrescribir sus métodos: toString(), etc. Ejemplo: Copy // create custom exception class class NegativeNumberException implements Exception { // can contain constructors, variables and methods // method that returns custom error message String getErrorMessage() => "Value must be greater than 0"; } void main() { // lets thwow and catch custom exception when value is < 0 try { int number = -20; // negative value if (number < 0) { throw NegativeNumberException(); } } on NegativeNumberException catch (e) { print(e.getErrorMessage()); // prints: Value must be greater than 0 } } [PreviousClases Callable (Callable objects)](https://ecm-pmdm-flutter.gitbook.io/dart/clases/clases-callable-callable-objects) [NextProgramación funcional](https://ecm-pmdm-flutter.gitbook.io/dart/programacion-funcional) Last updated 18 hours ago --- # Clases | Dart Las **clases** en **Dart** son **similares** a **Java**_**.**_ De herencia simple, **todos** los **objetos** en Dart, incluso los tipos primitivos, son instancia de una clase. Todas las clases, excepto Null, derivan de la clase Object que proporciona por defecto: * toString() -> devuelve la representación en cadena del objeto * hashCode -> _getter_ que devuelve el código hash del objeto * operador `**==**` \-> permite determinar si dos objetos son iguales **A tener en cuenta en Dart:** * El uso de **new** para instanciar objetos es **opcional (no se escribe por convención)** * No existen los calificadores: _**public, private o protected**__._ * Todos los **miembros** de la clase son **públicos** **por** **defecto**. * Para hacer un **miembro** **privado** en la _library_ (toda aplicación Dart es por defecto una _library_) usaremos la **barra baja \_** como prefijo al nombre del miembro. * Cada variable (atributo) de instancia tiene implícito un **getter** y un **setter**. También podemos implementarle las propiedades `get` y `set` si es necesario. * No se puede definir una clase dentro de otra clase (en Java sí podemos anidar clases). * En un **mismo** **fichero** .**dart** podemos definir **varias** **clases**. #### [](https://ecm-pmdm-flutter.gitbook.io/dart/clases#undefined) [PreviousDart Core Libraries](https://ecm-pmdm-flutter.gitbook.io/dart/dart-core-libraries) [NextConstructores](https://ecm-pmdm-flutter.gitbook.io/dart/clases/constructores) Last updated 1 day ago --- # Clases abstractas | Dart * Una **clase** **abstracta** **no** **puede** **instanciarse.** * Útil para definir interfaces, incluso con alguna implementación. Ejemplo: Copy void main() { // var abstract = AbstractContainer(); // error, can't be instantiated var myCont = MyContainer(); myCont.printClassName(); } // This class is declared abstract and thus can't be instantiated. abstract class AbstractContainer { // Define constructors, fields, methods... void updateChildren(); // Abstract method, no implemented, must be overrided void printClassName() { print("This is ${runtimeType} class"); // prints: This is MyContainer class } } class MyContainer extends AbstractContainer{ int numElements = 10; @override void updateChildren() { // TODO: must implement updateChildren } } [PreviousTipos enumerados](https://ecm-pmdm-flutter.gitbook.io/dart/clases/tipos-enumerados) [NextInterfaces implícitas](https://ecm-pmdm-flutter.gitbook.io/dart/clases/interfaces-implicitas) Last updated 20 hours ago --- # Variables y métodos de clase (static) | Dart **Similar a Java:** * Las variables y métodos **estáticos** se llaman: variables de clase y métodos de clase. * Las variables estáticas no se inician hasta que no se usan. (_lazily_ _initialized_) * Un método estático no tiene acceso a variables ni métodos de instancia sólo a variables y métodos estáticos, por tanto, no puede utilizar `_this_`. **Ejemplos**: Ejemplo1: Constantes de clase Ejemplo 2: Métodos de clase Las variables estáticas son útiles para definir constantes de clase: Copy class MyQueue { static const initialCapacity = 16; // ··· } void main() { assert(MyQueue.initialCapacity == 16); } Copy import 'dart:math'; void main() { var a = Point(2, 2); var b = Point(4, 4); var distance = Point.distanceBetween(a, b); assert(2.8 < distance && distance < 2.9); print("Distance between: $a and $b is $distance"); } class Point { double x, y; Point(this.x, this.y); static double distanceBetween(Point a, Point b) { // class method var dx = a.x - b.x; var dy = a.y - b.y; return sqrt(dx * dx + dy * dy); } @override String toString() { return "[$x, $y]"; } } El programa anterior muestra: Distance between: \[2, 2\] and \[4, 4\] is 2.8284271247461903 [PreviousConstructores](https://ecm-pmdm-flutter.gitbook.io/dart/clases/constructores) [NextHerencia y sobrescritura. Propiedades get y set.](https://ecm-pmdm-flutter.gitbook.io/dart/clases/herencia-y-sobrescritura.-propiedades-get-y-set.) Last updated 21 hours ago --- # Conceptos básicos | Dart Preguntas Solución Selecciona para cada cuestión la opción correcta: 1. Dart es un lenguaje de: Programación Orientado a objetos / Programación funcional 2. Dart ha sido desarrollado por: Facebook/Google/Microsoft/IBM 3. VS Code es: un Lenguaje de programación / Framework / IDE 4. La extensión de un fichero que contiene código fuente Dart es: .drt / .dar / .dart 5. En Dart el uso de ; al final de una sentencia es: Obligatorio / Opcional 6. Un programa en Dart necesita de una función main() para ejecutarse: Verdadero / Falso 7. En Dart los bloques de código se delimitan con: \[ \] / { } / ( ) 8. El uso de la palabra reservada _new_ para instanciar objectos en Dart es: Obligatorio / Opcional. 9. Dart es null-safe, lo que significa que las variables tienen por defecto valor null: Verdadero / Falso 10. El Dart runtime gestiona: memoria, garbage collection, threads, excepciones,..etc. Verdadero / Falso 1. Orientado a objetos 2. Google 3. IDE 4. .dart 5. Obligatorio 6. Verdadero 7. { } 8. Opcional 9. Falso (no pueden ser null! a no ser que se indique en el tipo de datos) 10. Falso (no hay _threads_ en Dart sino _isolates,_ más seguros pues no comparten estado) [PreviousGuia para escribir código Dart standard, claro y efectivo](https://ecm-pmdm-flutter.gitbook.io/dart/guia-para-escribir-codigo-dart-standard-claro-y-efectivo) [NextProgramación básica](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-basica) Last updated 3 hours ago --- # Programación básica | Dart Ejercicio 1: Variables y tipos de datos[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-basica#ejercicio-1-variables-y-tipos-de-datos) Define variables del tipo adecuado para guardar los siguientes valores e imprime en pantalla el valor de cada una. `country='Finland';` `year = 2050;` `length = 1.259;` `single = true;` La **salida** será: Copy Finland 2050 1.259 true Ejercicio 2: String Interpolation1[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-basica#ejercicio-2-string-interpolation1) Define una variable String con tu **nombre** y otra variable String con tus **apellidos**. Utiliza la interpolación de cadenas para imprimir en pantalla el siguiente mensaje a partir tus variables definidas: "ALUMNO: tus\__apellidos, tu\_n_ombre". \-> Si tienes instalado el Dart SDK puedes probar a leer los datos del teclado con la función stdin.readLineSync() de la biblioteca _'dart:io'_ Imprime también el mensaje anterior con: * Todas las letras en mayúscula. * Todas las letras en mínúscula. Ejemplo de salida para el nombre Joan y los apellidos Martorell Lluna: Copy ALUMNO: Martorell Lluna, Joan ALUMNO: martorell lluna, joan ALUMNO: MARTORELL LLUNA, JOAN Ejercicio 3: String Interpolation2[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-basica#ejercicio-3-string-interpolation2) Dadas las siguientes variables: Copy double temperature = 20; String temperatureScale = 'Celsius'; int value = 2; String rice = 'arroz'; String vegetables = 'verduras'; Escribe un programa que imprima en pantalla la siguiente salida utilizando las variables anteriores: Copy La temperatura es de 20 grados Celsius. 2 mas 2 es igual a 4. Me gusta el arroz y las verduras. **Atención**: La salida deberá cambiar correctamente dependiendo de los valores asignados a ls variables. Por ejemplo, si value=5, la salida será: Copy 5 mas 5 es igual a 10.exp Ejercicio 4 : Conversiones de temperatura[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-basica#ejercicio-4-conversiones-de-temperatura) Dada la siguiente variable: Copy double tempFarenheit = 92.67; Escribe un programa que convierta esta temperatura a grados Celsius. Utiliza esta fórmula: Copy Fahrenheit to Celsius: (°F − 32) / 1.8 = °C Imprime el resultado de la conversión. Para el valor anterior debería imprimirse: Copy 92.67F = 33.705555555555556C **Mejora** La temperatura convertida a grados celsius mostrará como máximo 1 decimal. (Ayuda: Utiliza un método de la clase double para la conversión a String deseada) Para el valor anterior debería imprimirse ahora: Copy 92.67F = 33.7C Ejercicio 5: if..else. (sueldo y gastos)[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-basica#ejercicio-5-if..else.-sueldo-y-gastos) Define dos **constantes** llamadas `salary` y `expenses` (sueldo y gastos). Escribe un programa que imprima en pantalla diferentes mensajes atendiendo a las siguientes condiciones: Copy Si sueldo > gastos Este mes has ahorrado: sueldo - gastos Euros. sino si gastos > sueldo Este mes has gastado de más: gastos - sueldo Euros. sino Este més no has ahorrado nada, te has gastado todo el sueldo. **Verifica** que el programa funciona correctamente para diferentes valores de sueldo y gastos. Ejercicio 6: switch (calculadora sencilla)[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/programacion-basica#ejercicio-6-switch-calculadora-sencilla) Completa el siguiente programa: Copy enum Operation { plus, minus, multiply, divide } void main() { const a = 7; const b = 5; const operation = Operation.plus; // TODO: implementa la calculadora } Utiliza una sentencia **switch** para que el programa sea capaz de imprimir el resultado correspondiente a la _operación_ seleccionada y el valor de las constantes _a_ y _b._ Con los valores actuales debería de imprimir: Copy 7 + 5 = 12 Para el resto de operaciones imprimiría: Copy // const op = Operation.minus; 7 - 5 = 2 // const op = Operation.multiply; 7 * 5 = 35 // const op = Operation.divide; // con dos decimales 7 / 5 = 1.40 Utiliza interpolación de cadenas. Verifica que el programa funciona correctamente probando diferentes valores para las constantes a y b. **Mejora** Añade al programa la operación llamada _**modulus**_ (que calcula el resto de la división). Comprueba su correcto funcionamiento. [PreviousConceptos básicos](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/conceptos-basicos) [NextColecciones](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/colecciones) Last updated 1 year ago --- # Tipos enumerados | Dart Los tipos enumerados o `enum` son una clase especial de Dart para **representar** un **número** **fijo** de **valores** **constantes.** Cada valor en un `enum` tiene una propiedad `getter` llamada `index`, que devuelve la **posición** del valor en el enum comenzando por el índice 0, como en las listas. Así, el primer valor tiene el índice 0, el segundo valor tiene el índice 1,.... **Ejemplo**: Copy enum Color { red, green, blue } void main() { List myColors = Color.values; // get all colors // Print: all values of enum: [Color.red, Color.green, Color.blue] print(myColors); var aColor = Color.blue; // Print: Color.blue --> has index: 2 print('Color.${aColor.name} --> has index: ${aColor.index}'); switch (aColor) { case Color.red: print('Red as roses!'); break; case Color.green: print('Green as grass!'); break; default: // Without case default:, you'll see a WARNING. // prints: Sorry, blue not allowed print("Sorry, ${aColor.name} not allowed"); } } [PreviousHerencia y sobrescritura. Propiedades get y set.](https://ecm-pmdm-flutter.gitbook.io/dart/clases/herencia-y-sobrescritura.-propiedades-get-y-set.) [NextClases abstractas](https://ecm-pmdm-flutter.gitbook.io/dart/clases/clases-abstractas) Last updated 20 hours ago --- # Futures, async/ await | Dart Dart soporta la programación asíncrona utilizando objetos del tipo **Future,** Streams y expresiones **async**/**await** Un Future es el tipo de objeto que devuelve una operación asíncrona. El _future_ representa el resultado de esa operación asíncrona. > Un Future es una promesa de que el objeto tendrá en algun momento del futuro un valor (o un error). Es similar al Promise de Javascript. El objeto _future_, puede estar: * _**incompleto:**_ todavía sin valor porque la operación está en la cola para ser ejecutada (o no ha terminado) * _**completo:**_ la operación ya ha terminado y el valor ya está disponible o termina con un error. > Hasta que el Future no está completo, su valor, no se puede utilizar. Para realizar operaciones asíncronas tenemos dos opciones: * Podemos utilizar directamente el API de Future y Stream * Utilizar _async_ y _await_ que es lo que se recomienda: el código asíncrono queda más claro al parecerse más a la forma en que escribimos el código síncrono. Podemos **crear** una **tarea** **asíncrona,** y que se añada a la cola de eventos, con uno de los constructores de la clase **Future**, por ejemplo: * Future( ) o, * Future.delayed( , ) ### [](https://ecm-pmdm-flutter.gitbook.io/dart/concurrencia-programacion-asincrona/futures-async-await#ejemplo-future-api) Ejemplo: Future API En el siguiente ejemplo vamos a simular que descargamos un fichero. La tarea tiene una duración de unos 6 segundos. Esta tarea se realizará de forma asíncrona para no bloquear el main(), se devolverá el valor del objeto Future utilizando el método Future.then() o el Error: Future completes with Value Future completes with Error Copy Future downloadFile() { Future result = Future.delayed(Duration(seconds: 6), () => "Cats, dogs and other pets"); // lambda is called when time expires --> // that returns a String (that simulates file content) return result; // returns Future: future object that will contain a String value } void main() { print('main starts !'); // calling downloadFile() function does not block main, // returns immediately (with incomplete future) // can't print the value because value is not yet available // we get printed: Instance of '_Future' print(downloadFile()); // to get the value: // use .then with the callback to execute if future completed with value downloadFile().then( (s) => print(s)); // s is the return value of Future print('main finishes !'); } El programa anterior muestra: > main starts ! Instance of '\_Future' main finishes ! Cats, dogs and other pets Copy // future will complete with error Future downloadFile() { Future result = Future.delayed(Duration(seconds: 6), () => throw "Error: download failed!"); return result; } void main() { print('main starts !'); downloadFile().then((s) => print(s)) // callback if future completes with a String value: s .catchError((e) => print(e)); // e is error message // equivalent, using onError: (named parameter) // downloadFile().then((s) => print(s), onError: (e) => print(e)); print('main finishes !'); } El programa anterior acaba con un error y muestra: > main starts ! main finishes ! Error: download failed! ### [](https://ecm-pmdm-flutter.gitbook.io/dart/concurrencia-programacion-asincrona/futures-async-await#ejemplo-async-await) Ejemplo: async/await Dart proporciona los modificadores _**async**_ y _**await**_ de la biblioteca _**dart:async**_, esto nos permitirá escribir código asíncrono como si fuese sincrono. Si queremos que una función pueda ejecutar código de forma asíncrona, deberemos de indicarlo con el modificador _**async**_ después del nombre de la función. > **Una función** _**async**_ **siempre devuelve un objeto Future** Si queremos esperar a que una operación asíncrona acabe, usaremos el modificador _**await**_. Cuando una función utiliza en su código _**await**_, deberemos **necesariamente** marcarla como _**async**_. > 🖐️ATENCIÓN: Una función _**async**_ ejecuta su código **síncronamente** hasta que encuentra el primer _**await**_, entonces retorna el objeto Future y la operación a realizar se pone en cola para ejecutarse asíncronamente. La función reanudará su ejecución cuando el await termine. Veamos el ejemplo anterior utilizando _async_ i _await:_ Copy // downloadFile() is now asynchronus // marked with "async" modifier: async function always returns Future object Future downloadFile() async { // Careful! --> function executes "synchronously" until it finds first await expression: print('...getting file from server...'); // at this point, function returns immediately a Future object // await operation is queued to execute asynchronously String fileContent = await Future.delayed(Duration(seconds: 6), () => " Cats, dogs and other pets"); // lambda is called when time expires --> returns String that simulates file content // async funcion resumes when await expression completes: fileContent expression is ready print("\nTHE CONTENT OF FILE IS: $fileContent"); } void main() { print('main() starts !'); // sync function print("async - Starting Downloading function ...."); // sync function downloadFile(); // async function: do not block main() print('main() finishes !'); } El programa anterior muestra: > main() starts ! async - Starting Downloading function .... ...getting file from server... > > main() finishes ! > > THE CONTENT OF FILE IS: Cats, dogs and other pets Otro ejemplo, esta vez creando una función asíncrona que realiza varias sumas: Future completado con valor Future completado con error Copy void main() { print('main() starts !'); // sync function print("\nasync - Starting Downloading function ...."); // sync function myAsyncSum(); print('main() finishes !'); } Future myAsyncSum() async { // async function: future not returning any value print("Starting sum in background\n"); // create a Future task that executes asynchronous code int totalSum = await Future( () => // the following is executed asynchronously getSum(5000000) + getSum(50000000) + getSum(5000000000)); print('TOTAL SUM = $totalSum'); } int getSum(int max) { int sum = 0; for (int i=1; i<=max; i++){ sum += i; } return sum; } El programa anterior muestra: > main() starts ! > > async - Starting Downloading function .... Starting sum in background > > main() finishes ! TOTAL SUM = 12501262500094487000 Usaremos _**try..catch**_ si el Future termina con error: Copy void main() { print('main() starts !'); // sync function print("\nasync - Starting Downloading function ...."); // sync function myAsyncSum(); print('main() finishes !'); } Future myAsyncSum() async { // async function: future not returning any value print("Starting sum in background\n"); try { // create a Future task that executes asynchronous code int totalSum = await Future(() { int total = getSum(100) + getSum(500) + getSum(1000); if (total > 100000) throw '\nError: Total Sum is > 100000!'; return total; }); print('TOTAL SUM = $totalSum'); } catch (e) { print(e); } } int getSum(int max) { int sum = 0; for (int i = 1; i <= max; i++) { sum += i; } return sum; } El programa anterior muestra: > main() starts ! > > async - Starting Downloading function .... > > Starting sum in background > > main() finishes ! > > Error: Total Sum is > 100000! [PreviousConcurrencia-Programación asíncrona](https://ecm-pmdm-flutter.gitbook.io/dart/concurrencia-programacion-asincrona) [NextPackages and Libraries](https://ecm-pmdm-flutter.gitbook.io/dart/packages-and-libraries) Last updated 1 year ago --- # Métodos de extensión | Dart [https://dart.dev/guides/language/extension-methods](https://dart.dev/guides/language/extension-methods) Permiten **añadir** **funcionalidad** (nuevos métodos, getters, setters u operadores) a una **clase** **existente** a cuyo código fuente, normalmente, no tenemos acceso y, por tanto, no tenemos forma de modificar. **Ejemplo**: Añadimos a la clase `DateTime` un getter que devuelve la fecha con formato personalizado. Copy extension on DateTime { String get formatDdMmYyyy { // get access to the instance in extension methods via 'this' keyword return "${this.day}-${this.month}-${this.year}"; } } void main() { final dateTime = DateTime.now(); print(dateTime.formatDdMmYyyy); } [PreviousMixins](https://ecm-pmdm-flutter.gitbook.io/dart/clases/mixins) [NextClases Callable (Callable objects)](https://ecm-pmdm-flutter.gitbook.io/dart/clases/clases-callable-callable-objects) Last updated 11 months ago --- # Interfaces implícitas | Dart * En Dart, **no existe una sintaxis específica para declarar una interface pura** (como ocurre en Java) Si la intención de una clase es ser solo una interfaz y no se quiere que se pueda hacer `extends` desde otras clases fuera de su propia biblioteca, podemos añadirle a `class` el modificador `interface` con lo cual la clase podrá implementarse pero no extenderse desde otras bibliotecas que no sean la propia. Más información sobre **modificadores** de **clase** en: [https://dart.dev/language/class-modifiers](https://dart.dev/language/class-modifiers) * Las clases se usan como **interfaces** **implícitas**: Todas las clases en Dart definen de forma implícita una interfaz que contiene todos los miembros de instancia de la clase así como todas las interfaces que implementa. * Se usará cuando no queremos heredar la implementación (código) sino sólo la API de otra clase, por tanto, se han de **redefinir** **todos** los **métodos** de las interfaces que se implementen. * Una clase puede implementar una o varias interfaces (separadas por comas) declarándolas con `implements` e implementando todas las API de las interfaces implementadas. [](https://ecm-pmdm-flutter.gitbook.io/dart/clases/interfaces-implicitas#ejemplo) Ejemplo: ----------------------------------------------------------------------------------------------- Copy void main() { Person empar = Person('Empar'); Impostor impostor = Impostor() .._name = 'Impostor'; // It will have no effect on impostor's name // prints: PERSON SAYS: Hello, Anna. I am Empar. print('PERSON SAYS: ${getGreet(empar, 'Anna')}'); // prints: IMPOSTOR SAYS: Hi Aitana. Do you know what my real name is?--> [???] print('IMPOSTOR SAYS: ${getGreet(impostor, 'Aitana')}'); } String getGreet(Person person, String toOther) => person.greet(toOther); // A person. The implicit public interface contains greet() class Person { // In the interface, but visible only in this library. final String _name; // Not in the interface, since this is a constructor. Person(this._name); // In the interface. String greet(String who) => 'Hello, $who. I am $_name.'; } // An implementation of the Person interface. class Impostor implements Person { static const _impostorName = '???'; @override String get _name => _impostorName; // ??? It's the name for any Impostor person @override set _name(String value) {} // do nothing for Impostor name @override String greet(String who) => 'Hi $who. Do you know what my real name is?--> [${_name}]'; } [PreviousClases abstractas](https://ecm-pmdm-flutter.gitbook.io/dart/clases/clases-abstractas) [NextMixins](https://ecm-pmdm-flutter.gitbook.io/dart/clases/mixins) Last updated 20 hours ago --- # Clases Callable (Callable objects) | Dart * Una _**Callable**_ _**class**_ permite **invocar** la **instancia** de la clase **como** **una** **función**. * Son esenciales en la filosofia funcional de Dart. * Para ello, la clase tiene que implementar el método `call()` Puntos clave de las clases _callable_[](https://ecm-pmdm-flutter.gitbook.io/dart/clases/clases-callable-callable-objects#puntos-clave-de-las-clases-callable) 1. **Sintaxis más limpia:** Permiten que el código sea más claro y elegante, especialmente cuando se usan objetos en contextos funcionales o en librerías que esperan funciones. 2. **Facilitan la reutilización y abstracción**: Una clase callable encapsula tanto el estado como el comportamiento de forma más compacta. Así, puedes tener un objeto que contenga datos y que, al invocarlo, ejecute directamente una lógica sobre esos datos. 3. **Patrones de diseño más flexibles:** Permiten imitar ciertos patrones de diseño como el patrón command, donde puedes crear objetos que representan acciones invocables. **Ejemplo** En el siguiente ejemplo, Person es una clase callable de forma que la propia instancia anna puede usarse como una función, obteniendo un **código** más **natural** y **flexible**. Copy class Person { // makes this class a callable class String call(int age, String name) => "Hi $name you are $age years old, so young!"; } void main() { var anna = Person(); // using person instance as function: print(anna(25, "Anna")); // prints: Hi Anna you are 25 years old, so young! } [PreviousMétodos de extensión](https://ecm-pmdm-flutter.gitbook.io/dart/clases/metodos-de-extension) [NextExcepciones](https://ecm-pmdm-flutter.gitbook.io/dart/excepciones) Last updated 19 hours ago --- # Mixins | Dart Los **Mixins** son la forma de **reutilizar** **código** en varias jerarquías de clases. * Para **definir** un _mixin_, utilizamos `**mixin**` en la declaración en vez de `**class**` * Si queremos utilizar el `mixin` como una clase normal, es decir, **vamos a instanciarlo**, lo declararemos como `**mixin class**`. * Tanto los _**mixins**_ como _**mixin classes**_ no pueden tener **ni** _**extends**_**, ni** _**with**_**,** **ni** **constructores**. * Para **restringir** qué clases pueden usar el mixin escribiremos después del nombre del mixin: `**on**` * Para **utilizar** los _mixins_ en otras clases: escribir (si es el caso, después de _extends_) `**with**` seguido de los nombres de los mixins separados por comas. [https://dart.dev/guides/language/language-tour#adding-features-to-a-class-mixins](https://dart.dev/guides/language/language-tour#adding-features-to-a-class-mixins) Article: [https://quickbirdstudios.com/blog/flutter-dart-mixins/](https://quickbirdstudios.com/blog/flutter-dart-mixins/) [](https://ecm-pmdm-flutter.gitbook.io/dart/clases/mixins#ejemplo) **Ejemplo**: ------------------------------------------------------------------------------------ Copy // Mixins example void main() { var scientist = Scientist(); // used as regular class or mixin print('SCIENTIST: '); scientist.doExperiment('COVID Test'); print('WORKER: '); Worker(2020, 'Anna') //using cascade operator on same instance ..workHard() ..play() ..attendConference('COVID org') ..doExperiment('Covid Test'); // var player = PianoPlayer(); // compiling error: mixins can't be instantiated } // regular class, couldn't be a mixin because it has a Constructor class Person { Person(this.personName); String personName =''; } // To create a mixin, create a class that extends Object // and declares no constructors // defining a mixin class mixin class Scientist { void doExperiment(String name) { print('I am able to do this experiment: $name.'); } void attendConference(String name) { print('"$name conference" is very interesting.'); } } // creating just a mixin: mixin PianoPlayer { void play() { print('I play the piano.'); } } // Use of mixins class Worker extends Person with Scientist, PianoPlayer{ Worker(this.contractYear, String name) : super(name); int contractYear; void workHard() { print('My name is $personName, working since $contractYear, and I work hard!'); } } El programa anterior muestra la siguiente **salida**: > SCIENTIST: > > I am able to do this experiment: COVID Test. > > WORKER: > > My name is Anna, working since 2020, and I work hard! > > I play the piano. > > "COVID org conference" is very interesting. > > I am able to do this experiment: Covid Test. [PreviousInterfaces implícitas](https://ecm-pmdm-flutter.gitbook.io/dart/clases/interfaces-implicitas) [NextMétodos de extensión](https://ecm-pmdm-flutter.gitbook.io/dart/clases/metodos-de-extension) Last updated 19 hours ago --- # Herencia y sobrescritura. Propiedades get y set. | Dart * Las subclases heredan todos los atributos y métodos de la superclase (pero **no se heredan** los **constructores**). * Si la subclase no declara constructores, sólo tendrá el constructor por defecto. * Las subclasses **pueden** **sobrescribir** de la superclase: métodos de instancia, atributos, getters, setters y operadores. Para ello, utilizaremos explícitamente `**@override**` **Ejemplos:** _**getter, setter,**_ **herencia** Rectangle (getters, setters) Person <- Worker Animal <- Cat Copy void main() { var rect = Rectangle(3, 4, 20, 2); assert(rect.right == 23); rect.right = 21; assert(rect.left == 1); print('T: ${rect.top} L: ${rect.left}, R: ${rect.right}, B: ${rect.bottom} '); } class Rectangle { double left, top, width, height; Rectangle(this.left, this.top, this.width, this.height); // Define two calculated properties: right and bottom. double get right => left + width; set right(double value) => left = value - width; double get bottom => top + height; set bottom(double value) => top = value - height; } Copy void main() { var worker = Worker.all('Peter', 2001, 70.0, 1.87, 9876); worker.setMarried = 1; // set value for property worker.printInformation(); } class Person { // instance variables with default getter and setter String name; int birthYear; double? height, weight; bool _married = false; // private field inside library // getter/setter properties for _married bool get isMarried => _married; set setMarried(int condition) => _married = (condition >= 2) ? true : false; // parameterized constructor Person(this.name, this.birthYear); // named constructors Person.height(this.name, this.birthYear, this.height); Person.weight(this.name, this.birthYear, this.weight); Person.all(this.name, this.birthYear, this.weight, this.height); void printInformation() { // multi-line String concatenation print( "My name is $name. I was born in year $birthYear." " I'm $height m height and $weight kilos weight." " I'm ${isMarried ? 'married' : 'not married'}."); } } class Worker extends Person { int workerId; Worker(String name, int birthYear, this.workerId) : super(name, birthYear); Worker.all(String name, int birthYear, double weight, double height, this.workerId) : super.all(name, birthYear, weight, height); @override void printInformation() { super.printInformation(); print("My worker id is: $workerId"); } } > El programa anterior muestra: > > My name is Peter. I was born in year 2001. I'm 1.87 m height and 70 kilos weight. I'm not married. My worker id is: 987 Copy void main() { List myPets = []; // empty List of Animal myPets.add(Animal("UNKOWN")); myPets.add(Cat('Persian', name: 'Bob')); // with name myPets.add(Cat('European')); myPets.add(Animal('Fish')); // list all animals eating bread for (final a in myPets) { a.eat( 'BREAD'); // polimorphism: calls eat() method from Animal or Cat class } // print name of 2nd animal and its runTime class print('\n${(myPets[1] as Cat).name} is a ${((myPets[1] as Cat).runtimeType).toString()}'); } class Animal { final String type; Animal(this.type); void eat(String food) => print("Animal of type: $type, eats $food"); } class Cat extends Animal { String? _name; // library private String? get name => _name?.toUpperCase(); // ?. --> only if _name != null set name(String? value) => _name = value; Cat(String type, {String? name}) : super(type) { this.name = name; } @override void eat(String food) => print("My cat ${name ?? ""} eats $food"); @override void run() {} // ERROR: must exist always in Animal superclass void sleep() {} // No error: it's new method in Cat class } > El programa anterior muestra: > > Animal of type: UNKOWN, eats BREAD My cat BOB eats BREAD My cat eats BREAD Animal of type: Fish, eats BREAD > > BOB is a Cat [PreviousVariables y métodos de clase (static)](https://ecm-pmdm-flutter.gitbook.io/dart/clases/variables-y-metodos-de-clase-static) [NextTipos enumerados](https://ecm-pmdm-flutter.gitbook.io/dart/clases/tipos-enumerados) Last updated 20 hours ago --- # Constructores | Dart * Permiten instanciar objetos de la clase y iniciar sus miembros. * Usaremos `_this_` para referirnos a la instancia actual. En Dart se recomienda usar `_this_` sólo cuando hay un conflicto de nombre. * Si no declaramos un constructor, la clase tiene implícito un **constructor** **por** **defecto** (mismo nombre de la clase y sin argumentos) * El **constructor** **con** **parámetros** (con mismo nombre de la clase) lo utilizaremos para iniciar las variables de instancia. Como la **inicialización** se realiza de forma frecuente, Dart permite hacerlo de una forma más simple y compacta, de forma **abreviada**: Inicialización abreviada Inicialización tradicional Copy class Person { String? name; // default value is null int? age; // default value is null // setting name and age before body runs Person(String this.name, int this.age){ print(name); print(age); } } Copy class Person { String? name; // default value is null int? age; // default value is null Person(String name, int age) { this.name = name; this.age = age; } } * En Dart, **no** se permite la **sobrecarga** de constructores, por tanto, se define: * **Un constructor por defecto,** o * **Un constructor con parámetros,** pero no los ambos a la vez. * Para tener más de un constructor, Dart permite definir **constructores con nombre** con la sintaxis: `NombreClase.nombreConstructor(parametros)` * Para llamar a un constructor de la superclase usaremos: **super** Copy class Employee extends Person { Employee() : super.fromJson(fetchDefaultData()); // ··· } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/clases/constructores#listas-de-inicializacion) **Listas de inicialización** También podremos **inicializar** las **variables** de **instancia** **antes de ejecutar el cuerpo del constructor** con listas de inicialización. Las pondremos después de los parámetros con `:` y separadas por `,` (muy cómodas para iniciar las variables del tipo _final_ a partir de los parámetros): Copy void main() { var p = Person.fromJson({'name': 'Joan', 'age': '33'}); print("Name: ${p.name}, Age: ${p.age} "); //prints: Name: 33, Age: Joan } class Person { final String name; final int age; // setting name and age before body runs Person.fromJson(Map personJson) : name = personJson['name']!, // bang operator tells Dart analizer that, // in fact, value will be not null age = int.parse(personJson['age']!) { print('from json: $name, $age'); } } ### [](https://ecm-pmdm-flutter.gitbook.io/dart/clases/constructores#otros-constructores) Otros constructores Constructores Constantes Constructores Factory Si vamos a **instanciar** **objetos** q**ue no van a cambiar nunca**, podemos hacer que estos objetos sean constantes en tiempo de compilación (sólo tendremos una instancia). Para ello, declaramos el constructor como `const` y todas las variables de instancia las declaramos como `final`. En la llamada al constructor, se deberá anteponer `const` para indicar que instanciamos un objeto constante. Si no se llama al constructor con `const` se crearà una nueva instancia. **Ejemplo**: Copy class InmutablePoint { final double x; final double y; const InmutablePoint(this.x, this.y); } void main() { var p1 = const InmutablePoint(10, 20); // create a constant-object var p2 = const InmutablePoint(10, 20); // create a constant-object if (p1 == p2) { print('p1 and p2 are the same instance'); } var p3 = InmutablePoint(10, 20); // new instance, not constant-object if (p3 != p1 && p3 !=p2) { print('p3 is different from p1 and p2'); } } Los constructores que se declaran `factory` **no siempre crean una nueva instancia** de la clase, sino que **permiten** **devolver** una **instancia** **previa** (cached) o una **instancia** de un **subtipo**. También permiten iniciar variables _final_ cuando, por la lógica asociada, no se puede hacer desde la lista de inicialización. Copy void main() { var logger = Logger('UI'); logger.log('Button clicked'); var logMap = {'name': 'UI'}; var loggerJson = Logger.fromJson(logMap); loggerJson.log("Exit App"); var logger2 = Logger('UI'); logger2.log("Action Canceled"); var logger3 = Logger('EVENTS'); logger3.log("click()"); logger3.log("clear()"); //assert(logger == loggerJson && logger == logger2); if (logger == loggerJson && logger == logger2) { print(">>>>>> Just one 'UI' Logger instance <<<<<<<<"); } if (logger != logger3) { print(">>>>>>'UI' Logger Instance != 'EVENTS' Logger Instance <<<<<<<<"); } // same msg list print("'UI' Log messages(from logger var): ${logger.logMessages.toString()}"); print("'UI' Log messages(from logger2 var): ${logger2.logMessages.toString()}"); print("'EVENTS' Log messages: ${logger3.logMessages}"); } class Logger { // _cache is library-private, thanks to the _ in front of its name. static final Map _cache = {}; final List logMessages = []; final String name; bool mute = false; Logger._internal(this.name); // named private constructor factory Logger(String name) { // Look up the value of key, or add a new entry if it isn't there. return Logger._cache.putIfAbsent(name, () => Logger._internal(name)); } factory Logger.fromJson(Map json) { return Logger(json['name'].toString()); } void log(String msg) { if (!mute) print(msg); // add msg to log list logMessages.add(msg); } } > El programa anterior muestra: > > Button clicked > > Exit App > > Action Canceled > > click() > > clear() > > \>>>>>>>>> Just one 'UI' Logger instance <<<<<<<<< > > \>>>>>>>>> 'UI' Logger Instance != 'EVENTS' Logger Instance <<<<<<<< > > 'UI' Log messages(from logger var): \[Button clicked, Exit App, Action Canceled\] > > 'UI' Log messages(from logger2 var): \[Button clicked, Exit App, Action Canceled\] 'EVENTS' Log messages: \[click(), clear()\] ### [](https://ecm-pmdm-flutter.gitbook.io/dart/clases/constructores#constructor-privado) Constructor privado Si no queremos que una clase se pueda instanciar, por ejemplo, sólo contiene, constantes miembros estáticos, definiremos un constructor privado con `_` Copy void main() { //var m = MyClass(); // error, not instantiable MyClass.printVal(); // prints:10 } class MyClass { static const int constValue = 10; MyClass._(); // library private constructor static void printVal(){ print(MyClass.constValue); } } [PreviousClases](https://ecm-pmdm-flutter.gitbook.io/dart/clases) [NextVariables y métodos de clase (static)](https://ecm-pmdm-flutter.gitbook.io/dart/clases/variables-y-metodos-de-clase-static) Last updated 21 hours ago --- # Clases | Dart ### [](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases#basic) Basic Ejercicio 1: Clase Estudiante.[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases#ejercicio-1-clase-estudiante) Dado el siguiente programa... Copy void main() { final student = { 'name': 'Anna', 'school': 'CIPFP BATOI', 'birthYear': 2000, 'studies': 'DAM', 'courseNumber': 2, }; print('Hola!, Mi nombre es ${student['name']}'); print('Soy estudiante de ${student['courseNumber']} de ${student['studies']} en el ${student['school']}'); print('Tengo: ${(DateTime.now().year) - int.parse(student['birthYear'].toString())} años'); } ...que muestra en pantalla la siguiente salida: Copy Hola!, Mi nombre es Anna Soy estudiante de 2 de DAM en el CIPFP BATOI Tengo: 22 años **Refactoriza** el código anterior: * Crea una **clase** `Student` que contendrá las siguientes propiedades (no nulas): `name`, `school`, `birthYear`, `studies`, `courseNumber`. > Define el constructor con parámetros con nombre e inicialización abreviada (todos son requeridos). * **Define** en la clase `Student` un **método** `showInformation()` que mostrará en pantalla los datos de un estudiante como en el programa anterior. * Desde main, crea **dos** **instancias** de Student y **muestra** en pantalla sus **datos** utilizando el método `showInformation()` Ejercicio 2: Valoración de tiendas con clases.[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases#ejercicio-2-valoracion-de-tiendas-con-clases) Partiendo de la siguiente clase Shop: Copy class Shop { const Shop({ required this.name, required this.type, required this.ratings, }); final String name; final String type; final List ratings; } **Añade** el código necesario a la clase anterior para que ofrezca la siguiente funcionalidad (utiliza _getters_ o _métodos_ según sea lo más apropiado) * Obtener el número de ratings. * Calcular la media de ratings (utiliza un _bucle_ o el operador _reduce_) > Si no hay ratings devolverá null **Verifica** que la funcionalidad programada creando una instancia y mostrando en pantalla: nombre de la tienda, número de valoraciones y valoración media. ### [](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases#advanced) Advanced Ejercicio 3: Herencia y polimorfismo. Figuras geométricas.[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases#ejercicio-3-herencia-y-polimorfismo.-figuras-geometricas) Implementa la funcionalidad descrita en los comentarios TODO del siguiente programa que define las clases `Shape`, `Circle`, `Triangle`, y `Square` Copy import 'dart:math'; void main() { } abstract class Shape { double get area; // TODO: define getter for perimeter } class Circle extends Shape { Circle(this.radius); final double radius; @override double get area => pi * radius * radius; @override // TODO: override perimeter getter property } class IsoscelesTriangle extends Shape { IsoscelesTriangle(this.base, this.height); final double base; final double height; // TODO: override area getter property // TODO: override perimeter getter property } class Square extends Shape { Square(this.side); final double side; // TODO: override area getter property // TODO: override perimeter getter property } **Fórmulas:** * Área del triángulo isósceles: (base∗altura)/2(base \* altura) / 2(base∗altura)/2​ * Área del cuadrado: lado∗ladolado \* ladolado∗lado​ * Perímetro del círculo: 2∗π∗radio2 \* \\pi \* radio2∗π∗radio​ * Perímetro del cuadrado: 4∗lado4 \* lado4∗lado​ * Perímetro del triángulo: 2∗lado+base2\*lado + base2∗lado+base ​ donde lado\=(base/2)2+altura2) lado = \\sqrt{(base/2)^2 + altura^2)}lado\=(base/2)2+altura2)​​ Una vez **completada** la funcionalidad de las clases anteriores: * **Añade** a la clase `Shape` un **método** `showValues()` que mostrará en pantalla el tipo de figura geométrica, su perímetro y su área. * **Implementa** el método **main()**: * Crea una **lista** de formas geométricas que contenga: 2 triángulos, tres cuadrados y cuatro círculos. * Haz un **recorrido** de la **lista** llamando al método `showValues()` sobre cada elemento de la lista. **Ejemplo** de **salida**: Copy Tipo figura: IsoscelesTriangle, área: 15.625, perímetro: 27.624689052802225 Tipo figura: IsoscelesTriangle, área: 18.75, perímetro: 20.811388300841898 Tipo figura: Square, área: 13.690000000000001, perímetro: 14.8 Tipo figura: Square, área: 9, perímetro: 12 Tipo figura: Square, área: 81, perímetro: 36 Tipo figura: Circle, área: 66.47610054996001, perímetro: 28.902652413026093 Tipo figura: Circle, área: 13.854423602330987, perímetro: 13.194689145077131 Tipo figura: Circle, área: 63.61725123519331, perímetro: 28.274333882308138 Tipo figura: Circle, área: 84.94866535306801, perímetro: 32.67256359733385 Ejercicio 4: Constructor factory. Serializar JSON. Clase Player.[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases#ejercicio-4-constructor-factory.-serializar-json.-clase-player) Dado el siguiente programa: _**\--> Lee la explicación de los TODOs antes de comenzar a modificar el código**_ Copy class Player { Player({required this.nickName, required this.score}); final String nickName; final int score; // TODO1: Implement fromJson factory constructor // TODO2: Implement toJson method } void main() { try { final player = Player.fromJson({ 'nickName': 'RedHero', 'score': 36456, // TODO4: Add more data to player }); print('JSON to Player: ${player.nickName} Score: ${player.score}'); print('Player to JSON: ${player.toJson()}'); print(''); // TODO3: create new players with wrong data or wrong/missing keys } catch (e) { print(e.toString()); } } **Explicación**: _**TODO 1**_**:** Implementa en `Player` un **constructor** _**Factory**_ llamado `fromJson` que instanciará un objeto de la clase `Player` a partir de un _Map_ (pares clave-valor) que recibe como parámetro. * Este constructor, antes de instanciar un _Player_, debe **comprobar** el _**Map**_ y lanzar una _**Exception**__('Datos del jugador incorrectos')_ si detecta algún problema que no pueda solucionar. Por tanto, se debe comprobar: * ...que el tipo de datos sea el correcto (recuerda que si la clave no existe en el Map, el tipo de datos es Null), * ...que el score sea un número positivo, * ...que el nombre del player no sea una cadena vacía (en ese caso, en vez de dar error, puedes asignarle un nombre por defecto 'Unknown player'), _**TODO 2**_**:** Implementa en `Player` un **método** llamado `toJson()` que **devuelve** un _**Map**_ con los datos de la instancia actual: `Map`. _**TODO 3:**_ crea _players_ que tengan datos incorrectos para comprobar que se muestra el mensaje de error. **SALIDA:** Tras la implementación, la **salida** para el programa anterior sería: Copy JSON to Player: RedHero Score: 36456 Player to JSON: {nickName: RedHero, score: 36456} Exception: Datos del jugador incorrectos _**TODO 4:**_ Añade **más** **datos** a `Player`, modifica todo lo necesario en el programa y comprueba que funciona correctamente. La salida en pantalla, por ejemplo, si le añadimos a nuestro player una **lista** **de** **armas** (weapons) sería: Copy JSON to Player: RedHero Score: 36456 Weapons: [Invisibilidad, Poción mágica, Súper velocidad] Player to JSON: {nickName: RedHero, score: 36456, weapons: [Invisibilidad, Poción mágica, Súper velocidad]} Ejercicio 5: Método de extensión para _int_[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases#ejercicio-5-metodo-de-extension-para-int) Crea una extensión llamada `**RangeList**` sobre la clase _int_ que defina un método llamado `_generateRangeTo_` _:_ * Este método tendrá como argumento un número entero: `int upTo`y devolverá una lista con todos los valores enteros dentro del rango en order creciente, incluido `upTo`. * Si el argumento `upTo` es menor que el valor actual, el método retornará una lista vacía. **Ejemplo** de uso: Copy void main() { var myRange10 = 1.generateRangeTo(10); print(myRange10); for (var i in 1.generateRangeTo(5)) { print(i); } print(5.generateRangeTo(15)); print(4.generateRangeTo(4)); print(5.generateRangeTo(0)); } * Salida en pantalla: Copy [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 1 2 3 4 5 [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] [] [] **Mejora:** Si el argumento es menor que el número actual, se generará la lista en orden inverso. Si son iguales, seguirá devolviendo una lista vacía. Así, para el main() anterior, la salida sería: Copy [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 1 2 3 4 5 [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] [] [5, 4, 3, 2, 1, 0] Ejercicio 6: Uso de Mixins - Student, Alien[](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/clases#ejercicio-6-uso-de-mixins-student-alien) Amplía el código de ejemplo de los mixins: * Crea una **clase** `Student` que extienda Person: * Como atributo de clase tendrá el nombre de la escuela donde estudia. (utiliza en el constructor parámetros con nombre) * Además, incluirá el _mixin_ `PianoPlayer`. Como es un estudiante deberá informar de ello: deberás sobrescribir el método play(), reutilizando el código del mixin y añadiendo los prints() necesarios. * Crea una **clase** `Alien`: que procede de un planeta y tiene las habilidades de un `Scientist` (no extiende de ninguna otra clase) * Desde main, crea **instancia** de `Student` y otra de `Alien`. Llama a los métodos de sus mixins. Para el alien: investiga a los humanos y asiste a una conferencia sobre el cambio climático. Ejemplo para Student**:** Copy final anna = Student(personName: 'Anna', school: 'Alcoi Music School'); anna.play(); y la salida esperada: ![](https://ecm-pmdm-flutter.gitbook.io/dart/~gitbook/image?url=https%3A%2F%2F1551469701-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FsGv3FSfnl3pEE6ftH9Ys%252Fuploads%252FB0KJ2oFyUOM2VpdE33x5%252Fimage.png%3Falt%3Dmedia%26token%3D1d5cb05b-bf02-4703-8a52-be95edfc8efe&width=300&dpr=4&quality=100&sign=74d2f00&sv=2) [PreviousFunciones](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/funciones) [NextExceptions](https://ecm-pmdm-flutter.gitbook.io/dart/ejercicios/exceptions) Last updated 11 months ago --- # Conceptos básicos | Dart Conceptos básicos | Dart ---