Del creador de Desarrollando aplicaciones móviles nativas con React Native, ahora llega un nuevo post sobre tecnologías cross-platform desde la visión de un programador web. En este caso analizamos Flutter.

Qué, por qué, dónde y cuándo sobre Flutter

Antes de nada, por situarnos en el ecosistema del desarrollo de apps para móviles (y sin considerar las tecnologías nativas propias de Android e iOS), las llamadas tecnologías cross-platform se distinguen de las llamadas híbridas en que no utilizan en ningún momento un navegador embebido o webview. Es decir, si trabajamos con Ionic o Apache Cordova estamos realizando aplicaciones híbridas utilizando nuestros conocidos HTML y CSS para pintar webs embebidas en una carcasa nativa. Pero, cuando hablamos de Flutter o React Native estamos dentro de las tecnologías cross-platform que al compilar producen apps completamente nativas sin intervención alguna de navegadores web para su ejecución.

Flutter es la apuesta de Google para desarrollar aplicaciones móviles nativas cross-platform, es decir dirigidas al desarrollo nativo en las dos principales plataformas nativas: iOS y Android (aunque actualmente también tienen en versión beta la posibilidad de compilar también para navegadores web).

La primera versión estable es la 1.0, publicada en Diciembre de 2018. Por aquella época, Facebook con React Native (su principal competencia) ya llevaba 3 años satisfaciendo las demandas cross-platform del mercado.

Adiós Javascript, hola Dart

Como lo hace React Native, Flutter produce código nativo para las dos plataformas con un solo código (single codebase). Los programadores web podíamos aprovechar nuestros conocimientos en Javascript al utilizar React Native, pero Flutter se desvincula del mundo web completamente al utilizar como lenguaje de programación Dart.

El lenguaje Dart lo estrenó Google en 2001 como una alternativa a Javascript para web. Javascript fue invencible en web, y Google vió la oportunidad de usarlo en tecnologías nativas. Pensamos que la decisión por parte de Google de elegir Dart fue que permite compilar builds de producción en AOT (ahead-of-time). De este modo el resultado de la compilación produce instrucciones nativas muy afinadas a los chip arm64 de los móviles. Esto supone una mejora en el rendimiento/velocidad que ofrece sobre las app de React Native con Javascript , que hace una compilación JIT (Just In Time) menos efectiva (véase en la imagen el componente Bridge que penaliza el rendimiento).

Centrándonos en Dart como lenguaje de programación y comparándolo con Javascript, a primera vista parecen muy similares en sintaxis:

Pero en el fondo son muy diferentes: JS es un lenguaje interpretado y de tipado libre y Dart está fuertemente tipado y es compilado. Sin entrar en las ventajas e inconvenientes de ambas estrategias, con Javascript conseguimos un desarrollo más cómodo y flexible y con Dart obtenemos un código más robusto en términos de tipado lo cual ayuda mucho a la hora de refactorizar sin errores.

Adiós HTML, hola “Widgets Hell”

Con Flutter el montaje del interfaz UI se hace con widgets (los widgets no son más que clases Dart utilizadas para construir UIs). Se sigue la estrategia declarativa de definir interfaces de React: cada widget se encarga de su renderizado basándose en su configuración y su estado interno. Es el framework el encargado de calcular las diferencias cuando el estado cambia y obtener los mínimos cambios necesarios.

Por tanto los layouts se hacen componiendo widgets. Por ejemplo, para crear el siguiente layout que muestra una fila de 3 columnas con iconos y labels en cada una de ellas:

Se plantean los siguientes widgets:

Al ser montados, componiendo widgets dentro de widgets, nos queda éste árbol de widgets:

Flutter en su core viene con una serie de widgets básicos, en los que destacan Row y Column que permiten crear layouts siguiendo el modelo flexbox.

Con los widgets que encontramos en el catálogo de Flutter podemos crear UIs con un aspecto uniforme entre plataformas. Aunque también podemos orientar la app a cada plataforma siguiendo las guías de diseño correspondientes: si vamos por Google Material tenemos el paquete Material widgets ya incluido como dependencia por defecto, pero si queremos acercarnos a las guías de diseño de Apple tenemos el paquete iOS-centric cuppertino.

Hablando de styling, Flutter en su documentación nos ayuda a los programadores web a encontrar equivalencias de HTML&CSS con la maquetación con widgets.

Acelera el Time-To-Market con las packages

Uno de los secretos de lo rápido que es construir apps con Flutter es su sistema de paquetes. A través de ellos, Flutter se abre a las aportaciones por parte de la comunidad de programadores, permitiendo tener aplicaciones en producción en tiempo record sin tener que desarrollar todo desde cero.

Todos los paquetes de Dart/Flutter son publicados en pub.dev o pub.dev/flutter, cubriendo las necesidades típicas como peticiones http, routing con fluro, integración con APIs nativos como url_launcher y battery o utilización de plataformas de terceros como el caso de Firebase con FlutterFire.

pub.dev/flutter, además de actuar como portal para filtrar/buscar el paquete que deseemos, se muestran de inicio los paquetes con máxima puntuación (100) lo que indica que son completamente compatibles con Flutter. El análisis de los paquetes lo hace el propio equipo de Flutter, dándoles a cada uno un score basado en tres métricas: popularidad, salud (métrica de calidad de código) y mantenimiento (ritmo de nuevas actualizaciones).

Por si no fuera poco a la hora de ayudarnos a decidir los paquetes adecuados, el equipo de Flutter también nos proporciona los Flutter Favorites los paquetes que según ellos deberíamos considerar primero a la hora de iniciar una aplicación.

Hola Mundo

Vamos a ver código. Lo primero es instalarnos el SDK de Flutter. Y en el caso de utilizar como editores de código Visual Code o Android Studio es muy,muy recomendado instalarse los plugins correspondientes: Visual Code plugin, Android Studio plugin.

Con todo eso instalado, teniendo algún emulador de móvil instalado o enchufando nuestro propio móvil por cable y siguiendo el Get Started de Flutter, podemos picarnos en tiempo record nuestro Hello World y verlo en vivo:

// Copyright 2018 The Flutter team. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

Algo más complejo es la starter app que obtenemos cuando creamos una nueva app con el comando “flutter create”. El fichero donde reside el código que inicia la aplicación es “lib/main.dart”:

import 'package:flutter/material.dart';

void main() {
 runApp(MyApp());
}

class MyApp extends StatelessWidget {
 // This widget is the root of your application.
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: 'Flutter Demo',
     theme: ThemeData(
       primarySwatch: Colors.blue,
       visualDensity: VisualDensity.adaptivePlatformDensity,
     ),
     home: MyHomePage(title: 'Flutter Demo Home Page'),
   );
 }
}

class MyHomePage extends StatefulWidget {
 MyHomePage({Key key, this.title}) : super(key: key);
 final String title;

 @override
 _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
 int _counter = 0;

 void _incrementCounter() {
   setState(() {
     _counter++;
   });
 }

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text(widget.title),
     ),
     body: Center(
       child: Column(
         mainAxisAlignment: MainAxisAlignment.center,
         children: <Widget>[
           Text(
             'You have pushed the button this many times:',
           ),
           Text(
             '$_counter',
             style: Theme.of(context).textTheme.headline4,
           ),
         ],
       ),
     ),
     floatingActionButton: FloatingActionButton(
       onPressed: _incrementCounter,
       tooltip: 'Increment',
       child: Icon(Icons.add),
     ), // This trailing comma makes auto-formatting nicer for build methods.
   );
 }
}

Nos renderiza lo siguiente:

Para mostrar código más cercano a lo que sería una app real hemos realizado una aplicación simple consistente en generar un avatar svg en función de un nickname y de una selección de género.

iOS emulator: iPhone 8

Android emulator: Pixel XL

Puedes consultar el código completo en este link.

Con este ejemplo (que me llevó una tarde) pretendo mostrar:

También podéis probar una app en producción como Codersnack publicada en Play Store, donde se puede ver mejor el rendimiento con un interfaz UI más avanzada.

React Native vs Flutter: Minuto y Resultado

A día de redactar este post, el minuto y resultado de la carrera entre las dos plataformas es la siguiente:

https://github.com/facebook/react-native/releases vs https://github.com/flutter/flutter

Como vemos React Native en este momento está por delante de Flutter en el mercado, aunque la tendencia es a igualarlo a medio plazo.

Conclusiones

Con este post no vais a tener la respuesta a la pregunta del millón: ¿Qué plataforma es mejor? En las redes hay abundantes análisis comparativos como este.

En resumen mis conclusiones son:

Por todo ello y en mi experiencia desarrollando con Flutter para Android, en estos momentos lo encuentro más satisfactorio que desarrollar con React Native+Expo. Aunque he de decir que se me quedan en el tintero aspectos como animaciones y aprovechamiento del hardware de los dispositivos para poder tener una opinión más firme.

Espero con este post haberos dado claves sobre esta plataforma y que os sirva de decisión para disfrutar haciendo vuestra creaciones móviles nativas para Android e iOS con el mismo código.

Referencias

Flutter.dev

Ahead-of-time compilation

Flutter vs. React Native: In a nutshell

Avatars

Cuéntanos qué te parece.

Enviar.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.

Suscríbete