En prenant du recul sur mon expérience avec Dart / Flutter, je constate l’ajout systématique d’une méthode dans chacun de mes projets : la méthode intersperse. Cette fonction me permet d’insérer un élément spécifique entre chaque paire d’éléments d’un Iterable. Bien que cette opération puisse sembler rudimentaire à première vue, elle facilite l’implémentation de certaines fonctionnalités (comme les espacements dans une Row de l’image de couverture, par exemple). Permettez-moi donc, de vous faire découvrir cette méthode très utile.

La méthode intersperse()

Comme explicité dans l’introduction, nous allons implémenter la méthode intersperse qui a pour objectif d’ajouter un intercalaire entre chaque paire d’éléments d’un Iterable.

Iterable<T> intersperse<T>(T element, Iterable<T> iterable) sync* {  
  final iterator = iterable.iterator;  

  if (iterator.moveNext()) {  
    yield iterator.current;  

    while (iterator.moveNext()) {  
      yield element;  
      yield iterator.current;  
    }  
  }  
}

La fonction intersperse s’appuie sur l’interface Iterable, ce qui lui permet de fonctionner de manière interchangeable avec toutes les collections qui implémentent cette interface (telles que List, Set, …).

La méthode intersperse est ce que la documentation de Dart appelle un “Lazy Synchronous Generator”. En d’autres termes, la méthode ne traitera que ce qui lui est demandé, sans excéder, offrant ainsi des gains de performances en fonction du contexte d’utilisation.

Pour l’implémentation, nous nous basons sur l’Iterator fourni par l’Iterable, dont la fonction est de parcourir progressivement la liste source. À chaque itération, il suffit d’ajouter l’élément intercalaire (d’où le nom de la méthode), et le tour est joué.

La méthode d’extension

Etant d’avis que cette méthode devrait faire partie de la bibliothèque standard de Dart, j’apprécie l’implémenter sous la forme d’une méthode d’extension. Cependant, en fonction des conventions de votre équipe, il se peut que l’utilisation des méthodes d’extension soit interdite dans votre codebase (je ne suis pas là pour remettre cet éternel débat sur le tapis à vos pauses cafés). Ci-dessous, je vous propose un exemple pour l’intégrer en tant que méthode d’extension. A vous de voir en fonction des habitudes de votre équipe.

import './intersperse.dart' as core;

extension IntersperseExtensions<T> on Iterable<T> {  
  Iterable<T> intersperse(T element) {  
    return core.intersperse(element, this);  
  }  
}

Exemple d’utilisation: ColumnWithGap

Afin de vous illustrer l’utilisation de cette méthode, je vous présente un exemple concret que j’ai implémenté dans plusieurs de mes projets : l’ajout de l’attribut gap aux widgets Column et Row. Cela permet d’introduire un espacement entre les enfants, une fonctionnalité que l’on retrouve en CSS mais qui fait défaut dans Flutter. Il est temps de remédier à cela.

class ColumnWithGap extends Column {  
  final double gap;  
  
  ColumnWithGap({  
    super.key,  
    super.mainAxisAlignment,  
    super.mainAxisSize,  
    super.crossAxisAlignment,  
    super.textDirection,  
    super.verticalDirection,  
    super.textBaseline,  
    required List<Widget> children,  
    required this.gap,  
  }) : super(  
    children: intersperse(SizedBox(height: gap), children).toList(),  
  );  
}
class RowWithGap extends Row {  
  final double gap;  
  
  RowWithGap({  
    super.key,  
    super.mainAxisAlignment,  
    super.mainAxisSize,  
    super.crossAxisAlignment,  
    super.textDirection,  
    super.verticalDirection,  
    super.textBaseline,  
    required List<Widget> children,  
    required this.gap,  
  }) : super(  
    children: intersperse(SizedBox(width: gap), children).toList(),  
  );  
}

Comme vous pouvez le voir, l’ajout de la méthode intersperse simplifie grandement l’implémentation de ses deux widgets. Il est assez facile d’imaginer d’autres usages.

A votre tour !

Cette méthode s’est avérée être précieuse dans l’ensemble de mes projets Flutter, et je suis sincèrement convaincu qu’elle mérite d’être intégrée à la bibliothèque standard, comme le suggère cette issue GitHub ouverte depuis septembre 2022 (Si vous aussi vous pensez que cette méthode devrait faire partie de la stdlib, n’hésitez pas à aller mettre un 👍 sur l’issue). Maintenant qu’elle est entre vos mains, je suis persuadé que vous trouverez de nombreuses autres applications auxquelles je n’avais pas encore pensé.