Continuamos la interpretación lacónica de la
documentación oficial de Flutter en un formato de preguntas y respuestas. Esta es la tercera parte, y será más útil para los desarrolladores de React Native. En esta interpretación, puede encontrar respuestas a las preguntas más frecuentes, así como determinar por sí mismo cuánto esfuerzo debe hacer para cambiar de un marco multiplataforma a otro.

Si esta información no es suficiente o si tiene experiencia en desarrollo nativo para una plataforma específica, le recomiendo buscar en otras partes:
Aleteo Parte 1. Para desarrolladores de AndroidAleteo Parte 2. Para desarrolladores de iOSAleteo Parte 3. Para desarrolladores nativos de ReactAleteo Parte 4. Para desarrolladores web
Aleteo Parte 5. Para desarrolladores de Xamarin.Forms
Contenido:
- Un poco sobre Dart
- Los fundamentos
- Estructura del proyecto y recursos
- Vistas
- Diseños
- Estilización
- Gestión del estado
- Almacenamiento local
- La navegación
- Gestos y manejo de eventos táctiles
- Solicitudes HTTP
- Formulario de entrada
- Código específico de plataforma
- Depuración
- Animación
- Equivalentes de componentes
- Flutter Plugins
Un poco sobre Dart
Pregunta:
¿Dónde está el punto de entrada?
La respuesta es:
Función
main()
.
Diferencias:
JavaScript no tiene un punto de entrada predefinido; puede ser cualquier función definida por el desarrollador. En Dart, esto es solo
main()
.
Pregunta:
¿Cómo salir a la consola?
La respuesta es:
Usando la función
print()
.
Diferencias:
En JavaScript, la salida de la consola se realiza mediante
console.log()
.
Un ejemplo:
print('Hello world!');
Pregunta:
¿Cómo crear y asignar variables / campos?
La respuesta es:
Dart admite la escritura dinámica y fuerte. Por lo tanto, las variables / campos se pueden crear en cualquier tipo de escritura que sea conveniente para usted. La asignación pasa por single =.
Diferencias:
La escritura fuerte no es compatible con JavaScript.
Informacion adicional:
Más detalles aquí.Un ejemplo:
String name = 'dart';
Pregunta:
¿Cuál es el valor predeterminado de una variable / campo?
La respuesta es:
null
Diferencias:
JavaScript
undefined
está
undefined
de forma predeterminada.
Informacion adicional:
Más detalles aquí.Pregunta:
¿Cómo verificar un valor para
null
o para 0?
La respuesta es:
Usando la verificación explícita
==
.
Diferencias:
En JavaScript, como parte de la verificación
if
, el número 1 o cualquier objeto
non-null
será equivalente a
true
. En Dart, solo un valor booleano de
true
equivalente a
true
.
Un ejemplo:
var myNull = null; if (myNull == null) { print('use "== null" to check null'); } var zero = 0; if (zero == 0) { print('use "== 0" to check zero'); }
Pregunta:
¿Cómo declarar funciones?
La respuesta es:
En Dart, las funciones, como los campos, pueden ser con tipeo dinámico o fuerte del valor de retorno. Los de tipo dinámico se declaran simplemente por el nombre de la función y, opcionalmente, por parámetros, mientras que los de tipo fuerte al principio todavía tienen un tipo de retorno.
Diferencias:
En JavaScript, una función se declara con la
function
palabra clave, seguida de un nombre y opcionalmente parámetros.
Informacion adicional:
Más detalles aquí.Un ejemplo:
fn() { return true; }
Pregunta:
¿Cuál es el equivalente de
Promise ?
La respuesta es:
FuturoInformacion adicional:
Dart, como JavaScript, admite la ejecución de un solo subproceso.
Future in Dart tiene el mismo significado que
Promise in React Native.
Más detalles aquí. .
Un ejemplo:
import 'dart:convert'; import 'package:http/http.dart' as http; class Example { Future<String> _getIPAddress() { final url = 'https://httpbin.org/ip'; return http.get(url).then((response) { String ip = jsonDecode(response.body)['origin']; return ip; }); } } main() { final example = new Example(); example ._getIPAddress() .then((ip) => print(ip)) .catchError((error) => print(error)); }
Pregunta:
¿Cuál es el análogo de
async
y
await
?
La respuesta es:
async
y
await
Diferencias:
En JavaScript, las funciones asíncronas devuelven
Promise , en Dart, devuelven
Future . esperar sincrónicamente espera el resultado de llamar a una función asíncrona.
Informacion adicional:
Más detalles aquí.Un ejemplo:
import 'dart:convert'; import 'package:http/http.dart' as http; class Example { Future<String> _getIPAddress() async { final url = 'https://httpbin.org/ip'; final response = await http.get(url); String ip = jsonDecode(response.body)['origin']; return ip; } } main() async { final example = new Example(); try { final ip = await example._getIPAddress(); print(ip); } catch (error) { print(error); } }
Los fundamentos
Pregunta:
¿Cómo crear un proyecto de aplicación en Flutter?
La respuesta es:
- Uso del IDE con los complementos Flutter y Dart instalados.
- Usando el
flutter create {projectname}
.
Diferencias:
Para crear un proyecto en React Native, use el
create-react-native-app {projectname}
.
Informacion adicional:
Más detalles aquí.Pregunta:
¿Cómo iniciar la aplicación?
La respuesta es:
- Usar la función de ejecución en el IDE con los complementos Flutter y Dart instalados.
- Usando el comando
flutter run
.
Diferencias:
React Native utiliza los
npm run
o
yarn run
para iniciar la aplicación.
Pregunta:
¿Cómo importar widgets?
La respuesta es:
En Flutter, todos los widgets se dividen en paquetes, por lo que importar un paquete es suficiente para usar sus widgets.
Diferencias:
En React Native, debe importar cada widget.
Un ejemplo:
import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/my_widgets.dart';
Pregunta:
¿Cómo usar widgets y anidamiento para construir un árbol de widgets?
La respuesta es:
En Flutter, casi todo son widgets. Incluso el objeto de la aplicación es un widget. Cada widget se puede anidar en el padre. Al combinar widgets, crea una jerarquía llamada árbol de widgets. Es ella quien luego se convierte en una pantalla en la pantalla.
Un ejemplo:
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'), ), ), ); } }
Pregunta:
¿Cómo crear componentes reutilizables?
La respuesta es:
En Flutter, puede crear una clase de widget y reutilizarla. Los parámetros utilizados son campos de clase.
Diferencias:
En React Native, para cambiar los parámetros de un elemento reutilizado, debe marcarlos como accesorios.
Informacion adicional:
Los parámetros en el constructor se pueden declarar de dos maneras: mediante enumeración regular y opcional, usando llaves
{}
. Las diferencias ocurren cuando se usan parámetros para invocar al constructor.
En la enumeración habitual, todos los parámetros son obligatorios, y cuando se llama al constructor, no se puede especificar qué parámetro en particular se pasa, porque se deben al pedido.
Con el opcional, puede usar cualquier orden en el que se transmiten los parámetros, pero debe especificar qué parámetro específico se transmite o no transmitirlos. Para marcar un parámetro opcional según sea necesario, use la anotación
@required
.
Un ejemplo:
class CustomCard extends StatelessWidget { CustomCard({@required this.index, @required this.onPress}); final index; final Function onPress; @override Widget build(BuildContext context) { return Card( child: Column( children: <Widget>[ Text('Card $index'), FlatButton( child: const Text('Press'), onPressed: this.onPress, ), ], ) ); } } ...
Estructura del proyecto y recursos
Pregunta:
¿Dónde comenzar a escribir código?
La respuesta es:
En
{projectname}/lib/main.dart
.
Pregunta:
¿Cuál es la estructura del archivo en un proyecto Flutter?
La respuesta es:
┬ └ projectname ┬ ├ android - Android . ├ build - iOS Android . ├ ios - iOS . ├ lib - Dart . ┬ └ src - Contains additional source files. └ main.dart - . ├ test - . └ pubspec.yaml - . package.json React Native.
Pregunta:
¿Dónde almacenar recursos y activos y cómo usarlos?
La respuesta es:
Los enlaces a recursos y dependencias del proyecto se almacenan en el archivo
pubspec.yaml
. De hecho, puede colocarlos en cualquier carpeta dentro de
lib
, lo más importante, especificar la ruta a ellos en
pubspec.yaml
. Puede usarlos en un proyecto usando widgets especializados, por ejemplo
AssetImage , o directamente usando
AssetBundle .
Informacion adicional:
Más detalles aquí.Un ejemplo:
Declarando activos en
pubspec.yaml
flutter: assets: - assets/my_icon.png - assets/background.png
Usar en código
image: AssetImage('assets/background.png'),
Pregunta:
¿Cómo descargar imágenes de la red?
La respuesta es:
Usando
Image.network .
Un ejemplo:
body: Image.network( 'https://flutter.io/images/owl.jpg',
Pregunta:
¿Cómo conectar paquetes y complementos de terceros?
La respuesta es:
Uso de
dependencies
en
pubspec.yaml
.
Diferencias:
React Native utiliza los comandos
yarn add {package-name}
o
npm install --save {package-name}
para agregar dependencias.
Informacion adicional:
Usando paquetesDesarrollo de paquetes y complementosComplementos populares para FlutterUn ejemplo:
dependencies: flutter: sdk: flutter google_sign_in: ^3.0.3
Vistas
Pregunta:
¿Cuál es el equivalente de un contenedor de
vista ?
La respuesta es:
Todos los widgets básicos para el diseño, por ejemplo
Contenedor ,
Columna ,
Fila y
Centro .
Informacion adicional:
Más detalles aquí.Pregunta:
¿Cuál es el análogo de
FlatList o
SelectionList ?
La respuesta es:
Vista de listaUn ejemplo:
var data = [ ... ]; ListView.builder( itemCount: data.length, itemBuilder: (context, int index) { return Text( data[index], ); }, )
Pregunta:
¿Cómo usar Canvas?
La respuesta es:
Usando las
clases CustomPaint y
CustomPainter .
Diferencias:
En React Native, no hay forma de dibujar usando Canvas fuera de la caja. Hay complementos de terceros, por ejemplo
react-native-canvas
.
Un ejemplo:
class MyCanvasPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { Paint paint = Paint(); paint.color = Colors.amber; canvas.drawCircle(Offset(100.0, 200.0), 40.0, paint); Paint paintRect = Paint(); paintRect.color = Colors.lightBlue; Rect rect = Rect.fromPoints(Offset(150.0, 300.0), Offset(300.0, 400.0)); canvas.drawRect(rect, paintRect); } bool shouldRepaint(MyCanvasPainter oldDelegate) => false; bool shouldRebuildSemantics(MyCanvasPainter oldDelegate) => false; } class _MyCanvasState extends State<MyCanvas> { @override Widget build(BuildContext context) { return Scaffold( body: CustomPaint( painter: MyCanvasPainter(), ), ); } }
Diseños
Pregunta:
¿Cómo usar widgets para describir las propiedades de diseño?
La respuesta es:
Flutter utiliza widgets especializados para propiedades de diseño, por ejemplo:
Columna ,
fila ,
relleno ,
alinear ,
apilar .
Diferencias:
En React Native, la mayoría de las propiedades de diseño se pueden configurar con
props
.
Informacion adicional:
Lista completa de widgetsPregunta:
¿Cómo posicionar widgets en el diseño?
La respuesta es:
Para un posicionamiento absoluto, use el widget
Pila . Para el pariente: varios widgets y sus combinaciones, que se pueden encontrar
aquí .
Un ejemplo:
Stack( alignment: const Alignment(0.6, 0.6), children: <Widget>[ CircleAvatar( backgroundImage: NetworkImage( 'https://avatars3.githubusercontent.com/u/14101776?v=4'), ), Container( decoration: BoxDecoration( color: Colors.black45, ), child: Text('Flutter'), ), ], )
Estilización
Pregunta:
¿Cómo diseñar los componentes?
La respuesta es:
Muy a menudo, los widgets tienen una propiedad de
style
.
Diferencias:
React Native utiliza
stylesheets.create
para diseñar.
Un ejemplo:
var textStyle = TextStyle(fontSize: 32.0, color: Colors.cyan, fontWeight: FontWeight.w600); ... Center( child: Column( children: <Widget>[ Text( 'Sample text', style: textStyle, ), Padding( padding: EdgeInsets.all(20.0), child: Icon(Icons.lightbulb_outline, size: 48.0, color: Colors.redAccent) ), ], ), )
Pregunta:
¿Cómo usar iconos y colores?
La respuesta es:
Usando las clases de
iconos y
colores .
Diferencias:
React Native no tiene soporte de iconos fuera de la caja.
Un ejemplo:
Íconos
Icon(Icons.lightbulb_outline, color: Colors.redAccent)
Colores
class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, textSelectionColor: Colors.red ), home: SampleAppPage(), ); } }
Pregunta:
¿Cómo personalizar el tema estilístico de la aplicación?
La respuesta es:
Usando la clase
ThemeData .
Diferencias:
En React Native, un tema común se configura a través de
stylesheets
.
Un ejemplo:
@override Widget build(BuildContext context) { return Theme( data: ThemeData( primaryColor: Colors.cyan, brightness: brightness, ), child: Scaffold( backgroundColor: Theme.of(context).primaryColor, ... ... ), ); }
Gestión del estado
Pregunta:
¿Cómo actualizar la visualización de widgets?
La respuesta es:
Usando
StatefulWidget y su
estado . Flutter tiene 2 tipos de widgets:
StatelessWidget y
StatefulWidget . Funcionan de la misma manera, la única diferencia está en el estado de representación.
Diferencias:
StatelessWidget tiene un estado inmutable. Adecuado para mostrar texto, logotipo, etc. Es decir Si el elemento en la pantalla no debe cambiar durante todo el tiempo de visualización, entonces le conviene. También se puede usar como contenedor para widgets con estado.
StatefulWidget tiene el estado
State , que almacena información sobre el estado actual. Si desea cambiar un elemento en la pantalla al realizar alguna acción (una respuesta vino del servidor, el usuario hizo clic en un botón, etc.), esta es su opción.
Un ejemplo:
1) StatelessWidget - Texto
Text( 'I like Flutter!', style: TextStyle(fontWeight: FontWeight.bold), );
2) StatefulWidget: cuando hace clic en el botón (FloatingActionButton), el texto en el widget de texto cambia de
Me gusta Flutter a
Flutter es impresionante. import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget {
Almacenamiento local
Pregunta:
¿Cómo almacenar datos de
key-value
en una aplicación?
La respuesta es:
Usando el complemento
shared_preferences .
Diferencias:
React Native utiliza
AsyncStorage .
Un ejemplo:
Adicción
dependencies: flutter: sdk: flutter shared_preferences: ^0.4.3
Uso
SharedPreferences prefs = await SharedPreferences.getInstance(); _counter = prefs.getInt('counter'); prefs.setInt('counter', ++_counter); setState(() { _counter = _counter; });
Pregunta:
¿Cómo almacenar datos complejos?
La respuesta es:
Uso de complementos de bases de datos, por ejemplo,
sqflite o
colmena .
La navegación
Pregunta:
¿Cómo navegar entre pantallas?
La respuesta es:
Para navegar entre pantallas, se utilizan las clases
Navegador y
Ruta .
Diferencias:
React Native utiliza
StackNavigator ,
TabNavigator y
DrawerNavigator .
Flutter tiene dos métodos de navegación:
- Describa un mapa con nombres de ruta
- Navega directamente a la ruta .
El navegador puede hacer
push () o
pop () a la ruta que especifique.
Un ejemplo:
void main() { runApp(CupertinoApp( home: MyAppHome(),
Pregunta:
¿Cómo usar la navegación por pestañas?
La respuesta es:
Uso de clases:
TabController ,
TabBar ,
Tab y
TabBarView .
Diferencias:
React Native utiliza
createBottomTabNavigator y TabNavigation .
Informacion adicional:
Más detalles aquí. .
Un ejemplo:
class _NavigationHomePageState extends State<NavigationHomePage> with SingleTickerProviderStateMixin { TabController controller=TabController(length: 2, vsync: this); @override Widget build(BuildContext context) { return Scaffold( bottomNavigationBar: Material ( child: TabBar( tabs: <Tab> [ Tab(icon: Icon(Icons.person),) Tab(icon: Icon(Icons.email),), ], controller: controller, ), color: Colors.blue, ), body: TabBarView( children: <Widget> [ home.homeScreen(), tabScreen.tabScreen() ], controller: controller, ) ); } }
Pregunta:
¿Cómo usar la navegación de cajones?
La respuesta es:
Usando la clase
Drawer .
Diferencias:
React Native utiliza
createDrawerNavigator y DrawerNavigation .
Un ejemplo:
@override Widget build(BuildContext context) { return Scaffold( drawer: Drawer( child: ListTile( leading: Icon(Icons.change_history), title: Text('Screen2'), onTap: () { Navigator.of(context).pushNamed('/b'); }, ), elevation: 20.0, ), appBar: AppBar( title: Text('Home'), ), body: Container(), ); }
Gestos y manejo de eventos táctiles
Pregunta:
¿Cómo manejar un clic?
La respuesta es:
Si el widget admite clics, entonces en
onPressed()
. De lo contrario, utilice el widget
GestureDetector .
Diferencias:
React Native utiliza
PanResponder o
Touchable para esto.
Un ejemplo:
GestureDetector( child: Scaffold( appBar: AppBar( title: Text('Gestures'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('Tap, Long Press, Swipe Horizontally or Vertically '), ], ) ), ), onTap: () { print('Tapped'); }, onLongPress: () { print('Long Pressed'); }, onVerticalDragEnd: (DragEndDetails value) { print('Swiped Vertically'); }, onHorizontalDragEnd: (DragEndDetails value) { print('Swiped Horizontally'); }, );
Solicitudes HTTP
Pregunta:
¿Cómo obtener datos de las solicitudes de API?
La respuesta es:
Usando un
complemento http .
Diferencias:
React Native utiliza la
fetch API
.
Un ejemplo:
Conexión de complemento
dependencies: flutter: sdk: flutter http: <latest_version>
Recuperación de datos
final url = Uri.https('httpbin.org', 'ip'); final httpClient = HttpClient(); _getIPAddress() async { var request = await httpClient.getUrl(url); var response = await request.close(); var responseBody = await response.transform(utf8.decoder).join(); String ip = jsonDecode(responseBody)['origin']; setState(() { _ipAddress = ip; }); }
Formulario de entrada
Pregunta:
¿Qué widgets usar para la entrada?
La respuesta es:
TextField junto con
TextEditingController o
TextFormField .
Diferencias:
React Native utiliza
TextInput .
TextFormField difiere de
TextField en su validación y lógica incorporadas para almacenar valores en los campos.
Un ejemplo:
Campo de texto
final TextEditingController _controller = TextEditingController(); ... TextField( controller: _controller, decoration: InputDecoration( hintText: 'Type something', labelText: 'Text Field ' ), ), RaisedButton( child: Text('Submit'), onPressed: () { showDialog( context: context, child: AlertDialog( title: Text('Alert'), content: Text('You typed ${_controller.text}'), ), ); }, ), )
TextFormField
final formKey = GlobalKey<FormState>(); ... Form( key:formKey, child: Column( children: <Widget>[ TextFormField( validator: (value) => !value.contains('@') ? 'Not a valid email.' : null, onSaved: (val) => _email = val, decoration: const InputDecoration( hintText: 'Enter your email', labelText: 'Email', ), ), RaisedButton( onPressed: _submit, child: Text('Login'), ), ], ), ) void _submit() { final form = formKey.currentState; if (form.validate()) { form.save(); showDialog( context: context, child: AlertDialog( title: Text('Alert'), content: Text('Email: $_email, password: $_password'), ) ); } }
Código específico de plataforma
Pregunta:
¿Cómo determinar en qué plataforma se está ejecutando el código?
La respuesta es:
Usando la clase de campo de
platform
en
Tema o la clase de
Plataforma .
Un ejemplo:
Campo de la plataforma
if (Theme.of(context).platform == TargetPlatform.iOS) { return 'iOS'; } else if (Theme.of(context).platform == TargetPlatform.android) { return 'android'; } else if (Theme.of(context).platform == TargetPlatform.fuchsia) { return 'fuchsia'; } else { return 'not recognised '; }
Clase de plataforma
if (Platform.isIOS) { return 'iOS'; } else if (Platform.isAndroid) { return 'android'; } else if (Platform.isFuchsia) { return 'fuchsia'; } else { return 'not recognised '; }
Pregunta:
¿Cómo llamar al código de plataforma nativa?
La respuesta es:
Vía
MethodChannel .
Informacion adicional:
Más detalles aquí. .
Depuración
Pregunta:
¿Cuáles son las herramientas para depurar la aplicación?
La respuesta es:
DevToolsPregunta:
¿Cómo hacer
hot reload
?
La respuesta es:
Si la aplicación se inició desde IntelliJ IDE o Android Studio,
⌘s/ctrl-s
o haga clic en el icono de
hot reload
. Si comenzó desde la terminal, ingrese la letra
r
.
Diferencias:
React Native utiliza
⌘R/Ctrl+R
para emuladores de iOS, doble
R
para Android.
Pregunta:
¿Cómo acceder al menú de desarrollador en la aplicación?
La respuesta es:
Si el lanzamiento fue desde el IDE, entonces usando las herramientas IDE. Si desde la consola, use h.
Diferencias:
React Native utiliza
⌘D/Ctrl+D
para emuladores de iOS y
⌘M/Ctrl+M
para Android.
Informacion adicional:
Lista completa de equipos
Animación
Pregunta:
¿Qué se usa para la animación?
La respuesta es:
Animación y
AnimationController .
Diferencias:
React Native utiliza la
Animation API
.
Informacion adicional:
Más detalles aquí.Pregunta:
¿Cómo agregar una animación de
fade-in
simple?
La respuesta es:
Usando
FadeTransition .
Un ejemplo:
import 'package:flutter/material.dart'; void main() { runApp(Center(child: LogoFade())); } class LogoFade extends StatefulWidget { _LogoFadeState createState() => _LogoFadeState(); } class _LogoFadeState extends State<LogoFade> with TickerProviderStateMixin { Animation animation; AnimationController controller; initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 3000), vsync: this); final CurvedAnimation curve = CurvedAnimation(parent: controller, curve: Curves.easeIn); animation = Tween(begin: 0.0, end: 1.0).animate(curve); controller.forward(); } Widget build(BuildContext context) { return FadeTransition( opacity: animation, child: Container( height: 300.0, width: 300.0, child: FlutterLogo(), ), ); } dispose() { controller.dispose(); super.dispose(); } }
Pregunta:
¿Cómo agregar animación de deslizamiento para enumerar elementos?
La respuesta es:
Uso
Descartable .
Un ejemplo:
child: Dismissible( key: key, onDismissed: (DismissDirection dir) { cards.removeLast(); }, child: Container( ... ), ),
Equivalentes de componentes
Pregunta:
¿Cuáles son los equivalentes de Flutter en comparación con React Native?
La respuesta es:
Flutter Plugins
Pregunta:
¿Cómo acceder al GPS?
La respuesta es:
Usando el complemento
geolocalizador .
Pregunta:
¿Cómo acceder a la cámara?
La respuesta es:
Usando el complemento
image_picker .
Pregunta:
¿Cómo iniciar sesión a través de Facebook?
La respuesta es:
Usando el complemento
flutter_facebook_login .
Pregunta:
¿Cómo usar firebase?
La respuesta es:
Firebase es compatible con los
complementos de Flutter :
Aquí están quizás las respuestas a las preguntas básicas. Espero que mi interpretación te haya sido útil, y si todavía no estás escribiendo en Flutter, al menos piénsalo. Esto significa que puede haber una adición al estante de desarrolladores de Flutter, y juntos haremos del mundo un lugar mejor a través del prisma de las aplicaciones desarrolladas, convenientes y rápidas. Sí, ¡React no romperá a tu nativo!