Saltar al contenido principal

DevTools

Aprende a usar las DevTools de Dart al desarrollar apps de Flutter.

Aprende a usar el widget inspector y el property editor para depurar problemas de diseño (layout) y experimentar con propiedades en tiempo real.

Qué lograrás

Explora el widget tree de tu app con el widget inspector
Aprende a depurar problemas de diseño (layout) como las restricciones ilimitadas (unbounded constraints)
Experimenta con propiedades en tiempo real

Pasos

1

Introducción

A medida que tu app de Flutter crece en complejidad, se vuelve más importante entender cómo cada una de las propiedades del Widget afecta a la UI. Las DevTools de Dart y Flutter te proporcionan dos funciones particularmente útiles: el inspector de Widgets y el editor de propiedades.

Primero, inicia DevTools ejecutando los siguientes comandos mientras tu app se está ejecutando en modo debug. Ejecuta este comando en una ventana de terminal separada de donde se ejecuta tu app:

dart devtools

Ejecutar este comando inicia el servidor DevTools y abre la interfaz en un navegador.

Para conectar DevTools a tu app en ejecución:

  1. Busca la URL de DevTools impresa en la terminal donde se está ejecutando tu app (por ejemplo: Serving DevTools at http://127.0.0.1:9101).
  2. Copia esta URL.
  3. Pégala en la barra de conexión en la página del navegador de DevTools.
2

El widget inspector

El widget inspector te permite visualizar y explorar tu widget tree. Te ayuda a comprender el diseño de tu UI e identifica qué widgets son responsables de las diferentes partes de la pantalla. Al ejecutarse con la app que has construido hasta ahora, el inspector se ve así:

Una captura de pantalla de la herramienta widget inspector de Flutter.

Considera el widget GamePage que creaste en esta sección:

dart
class GamePage extends StatelessWidget {
  GamePage({super.key});

  final Game _game = Game();

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        spacing: 5.0,
        children: [
          for (var guess in _game.guesses)
            Row(
              spacing: 5.0,
              children: [
                for (var letter in guess) Tile(letter.char, letter.type)
              ]
            ),
        ],
      ),
    );
  }
}

Y cómo se usa en MainApp:

dart
class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(child: GamePage()),
      ),
    );
  }
}

En el widget inspector, deberías ver un árbol de exactamente los mismos widgets que están en tu código: MaterialApp como raíz, con Scaffold como su home, un AppBar como su appBar, y así sucesivamente en todo el árbol hasta los widgets Row con hijos Tile. Puedes seleccionar cualquier widget en el árbol para ver sus propiedades e incluso saltar a su código fuente en tu IDE.

3

Depuración de problemas de diseño (layout)

El widget inspector es quizás muy útil para depurar problemas de diseño (layout).

En ciertas situaciones, las constraints de un Widget no tienen límites, o son infinitas. Esto significa que ya sea el ancho máximo o la altura máxima está establecido en double.infinity. Un Widget que intenta ser tan grande como sea posible no funcionará de forma útil cuando se le da una constraint sin límites y, en modo de depuración, lanza una excepción.

El caso más común en el que una caja de renderizado (render box) termina con una restricción ilimitada es dentro de un widget de caja flexible (Row o Column), y dentro de una región desplazable (scrollable), como las subclases de ListView o ScrollView.

ListView, por ejemplo, intenta expandirse para ajustarse al espacio disponible en su dirección cruzada (cross-direction). Como si fuera un bloque de desplazamiento vertical que intenta ser tan ancho como su padre. Si anidas un ListView de desplazamiento vertical dentro de un ListView de desplazamiento horizontal, la lista interna intentará ser tan ancha como sea posible, lo cual es infinitamente ancha, ya que la externa es desplazable en esa dirección.

Quizás el error más común con el que te encontrarás al construir una aplicación de Flutter se debe al uso incorrecto de widgets de diseño (layout). Este error se conoce como el error de restricciones ilimitadas ("unbounded constraints").

Mira el siguiente video para comprender cómo detectar y resolver este problema.

Ver en YouTube en una nueva pestaña: "Decoding Flutter: Alto y ancho ilimitados (Unbounded)"

4

El property editor

Cuando seleccionas un widget en el widget inspector, el property editor muestra todas las propiedades de ese widget seleccionado. Esta es una herramienta poderosa para comprender por qué un widget se ve de la manera en que lo hace y para experimentar con cambios en los valores de las propiedades en tiempo real.

Una captura de pantalla de la herramienta property editor de Flutter.

Mira el método build del widget Tile de antes:

dart
class Tile extends StatelessWidget {
  const Tile(this.letter, this.hitType, {super.key});

  final String letter;
  final HitType hitType;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 60,
      height: 60,
      decoration: BoxDecoration(
        border: Border.all(color: Colors.grey.shade300),
        color: switch (hitType) {
          HitType.hit => Colors.green,
          HitType.partial => Colors.yellow,
          HitType.miss => Colors.grey,
          _ => Colors.white,
        },
      ),
    );
  }
}

Si seleccionas el widget Container dentro de Tile en el widget inspector, el property editor muestra su width (60), height (60) y la propiedad decoration. Luego podrías expandir BoxDecoration para ver las propiedades border y color.

Para muchas propiedades, incluso puedes modificar sus valores directamente dentro del property editor. Por ejemplo, para probar rápidamente cómo se vería un width o height diferente para tu Container en el widget Tile, cambia el valor numérico en el property editor. La herramienta escribe esta actualización directamente de vuelta en tu archivo de código fuente .dart en el disco, lo que te permite ver instantáneamente la actualización visual en tu app en ejecución al guardar o al activar un Hot Reload. Esto permite una iteración rápida en el diseño de la UI.

5

Revisión

Qué lograste

Aquí tienes un resumen de lo que construiste y aprendiste en esta lección.
Exploraste el widget tree de tu app con el widget inspector

El widget inspector te permite visualizar todo tu widget tree, seleccionar cualquier widget para ver sus propiedades y saltar directamente a su código fuente. Es una herramienta esencial para comprender la estructura de tu app.

Aprendiste sobre problemas de diseño (layout) comunes

Aprendiste sobre las unbounded constraints, uno de los errores más comunes en el desarrollo de Flutter. Esto sucede cuando widgets como Row, Column o ListView reciben restricciones infinitas. Ahora puedes reconocer y solucionar estos problemas cuando ocurran.

Experimentaste con propiedades en tiempo real

El property editor muestra todas las propiedades de un widget seleccionado y te permite modificar valores directamente en el disco, permitiéndote ver las actualizaciones al instante al guardar o al activar un Hot Reload. Esto permite una iteración rápida al ajustar tu UI.

6

Ponte a prueba

Quiz de DevTools

1 / 2
What is a common cause of "unbounded constraints" errors in Flutter?
  1. Colocar un widget que intenta expandirse infinitamente dentro de un contenedor desplazable (scrollable) o flexible sin las restricciones adecuadas.

    ¡Así es!

    Los widgets como ListView dentro de un Row, o los desplazables anidados, pueden recibir restricciones infinitas y fallar.

  2. Usar demasiados StatefulWidgets en el widget tree.

    No exactamente.

    El uso de StatefulWidget no causa restricciones ilimitadas (unbounded constraints).

  3. Usar un Container sin especificar un color.

    No exactamente.

    El color es opcional y no está relacionado con las restricciones de diseño.

  4. Olvidar llamar a setState después de cambiar los datos.

    No exactamente.

    La falta de setState hace que la UI no se actualice, no causa errores de restricciones.

What can you do with the Widget Inspector in Flutter DevTools?
  1. Generar automáticamente pruebas unitarias para tus widgets.

    No exactamente.

    El widget inspector es para visualización y depuración, no para la generación de pruebas.

  2. Editar los colores de tema y la tipografía de tu app.

    No exactamente.

    La edición del tema requiere cambios de código; el widget inspector es para inspeccionar el state actual.

  3. Desplegar tu app directamente en la tienda de apps.

    No exactamente.

    El despliegue se maneja por separado; el widget inspector es para depuración.

  4. Visualizar tu widget tree, seleccionar widgets para ver sus propiedades y saltar al código fuente.

    ¡Así es!

    El widget inspector te permite explorar la estructura de tu app, inspeccionar las propiedades del widget y navegar al código fuente correspondiente.