Saltar al contenido principal

Clase IconData marcada como final

La clase IconData ahora está marcada como final, lo que evita que sea heredada (extended) o implementada.

Resumen

#

La clase IconData ahora está marcada como final, lo que evita que sea implementada o heredada. Este cambio es parte de un esfuerzo para generalizar el mecanismo de depuración de código muerto (tree-shaking) de recursos (assets) y código nativo.

Contexto

#

El equipo de Flutter está trabajando en un mecanismo generalizado para llevar el tree-shaking de recursos y código nativo a los paquetes. El actual optimizador personalizado (bespoke) Icon Tree Shaker se está integrando en este mecanismo general.

Por razones de rendimiento, localidad y legibilidad, el mecanismo general no admite el registro de instancias const en jerarquías de tipos complejas. Por lo tanto, la clase IconData ahora está marcada como final.

El código que implementa o hereda IconData ahora falla al compilar con el siguiente error:

The class 'IconData' is 'final' and can't be extended or implemented outside of its library.

Guía de migración

#

En lugar de implementar IconData, como con un enum que admita la notación abreviada de punto (dot shorthand), seguridad de tipos y una lista automatizada .values, utiliza una clase contenedora (wrapper class) con instancias static const.

Migrar tipos de iconos personalizados

#

Si utilizabas un enum que implementaba IconData, migra a una clase con instancias static const y un widget personalizado.

Código antes de la migración:

dart
enum AppIcons implements IconData {
  arrowUpward(0xe062),
  arrowDownward(0xe061);

  const AppIcons(this.codePoint)
    : fontFamily = 'MaterialIcons',
      fontPackage = null,
      matchTextDirection = false;

  @override
  final int codePoint;
  @override
  final String? fontFamily;
  @override
  final String? fontPackage;
  @override
  final bool matchTextDirection;
}

Widget build(BuildContext context) {
  // Example usage of AppIcons:
  return Icon(AppIcons.arrowUpward);
}

Para mantener el soporte de la notación abreviada de punto y la seguridad de tipos, utiliza una clase contenedora y un widget personalizado.

Código después de la migración:

dart
final class AppIconData {
  final IconData iconData;

  const AppIconData._(this.iconData);

  static const arrowUpward = AppIconData._(
    IconData(0xe062, fontFamily: 'MaterialIcons'),
  );
  static const arrowDownward = AppIconData._(
    IconData(0xe061, fontFamily: 'MaterialIcons'),
  );

  static const values = [arrowUpward, arrowDownward];
}

class AppIcon extends StatelessWidget {
  const AppIcon(this.icon, {super.key});
  final AppIconData icon;

  @override
  Widget build(BuildContext context) {
    return Icon(icon.iconData);
  }
}

Widget build(BuildContext context) {
  // Usage preserves dot shorthand if the type can be inferred:
  return const AppIcon(AppIconData.arrowUpward);
  // Or if inferred: const AppIcon(.arrowUpward)
}

Si dependes de .values para herramientas como Widgetbook, puedes mantener la lista de values manualmente como se muestra en el ejemplo anterior o utilizar generación de código.

Ignorar el lint mustBeConst

#

Para habilitar el tree-shaking, algunos parámetros de IconData están marcados con la anotación mustBeConst. Si debes usar un IconData que no sea const y estás dispuesto a prescindir del tree-shaking para ese icono, añade un comentario de omisión (ignore) para el lint.

dart
// ignore: non_const_argument_for_const_parameter
Icon(myDynamicIconData);

Timeline

#

Introducido en la versión: 3.44.0-0.1.pre
En el lanzamiento estable: 3.44

Referencias

#

PR relevante:

Issues relevantes: