Fin 2018, Google, avec l'aide de la communauté Open-Source, a fait un grand cadeau aux développeurs mobiles en publiant la première version stable du cadre de développement mobile multiplateforme Flutter.
Cependant, lors du développement de grandes applications légèrement plus volumineuses que les Hello Worlds d'une page, les développeurs peuvent rencontrer des incertitudes. Comment écrire une application? Le cadre est assez jeune, il n'y a toujours pas de base suffisante de bons exemples avec l'open source, sur la base desquels il serait possible de comprendre les avantages et les inconvénients de l'utilisation de divers modèles, de comprendre ce qui devrait être utilisé dans ce cas particulier et ce qui ne l'est pas.
La situation est sauvée par le fait que Flutter a un certain degré de similitude avec React et React Native, ce qui signifie que vous pouvez apprendre de certaines expériences de programmation dans ce dernier. Peut-être à cause de cela, des bibliothèques telles que Flutter Flux , Flutter Hooks , MobX , ainsi que plusieurs implémentations Redux sont apparues à la fois. Pendant longtemps, la version la plus populaire était Brian Egan appelée Flutter Redux .
Cependant, il y a quelques mois, le premier commit a été vu par la bibliothèque Fish Redux , publiée sous le nom d'Alibaba. La bibliothèque a rapidement gagné en popularité, déjà le premier jour avant la mise en œuvre de Brian en termes de nombre d'étoiles, et le deuxième jour, elle était deux fois plus rapide.
Malgré sa popularité, Fish a des problèmes avec la documentation, qui fournit pour la plupart une description des classes existantes avec quelques exemples courts. Pour aggraver les choses, certains documents ne sont disponibles qu'en chinois. Il y a une autre difficulté: il n'y a presque pas de problème anglophone, donc s'appuyer sur l'expérience des autres développeurs est très difficile, ce qui est très critique, étant donné que seules les premières versions d'aperçu sont publiées.
Alors, quelle est la différence significative entre la version Fish'a de Brian? Flutter Redux est un cadre de gestion d'état. Fish est un cadre d'application qui place Redux en son centre comme base de la gestion de l'État. C'est-à-dire Le poisson résout quelques tâches supplémentaires et ne se limite pas à state management
.
L'une des principales caractéristiques de Fish Redux est l'union de plusieurs réducteurs en plus grands par l'expression directe de la relation entre eux, alors que Redux normal ne fournit pas du tout une telle opportunité, forçant les développeurs à tout implémenter par eux-mêmes. Mais revenons à cela plus tard, après avoir traité de ce qu'est ce réducteur, ainsi que de Fish Redux lui-même.
La relation entre le réducteur, l'effet et la vue dans le composant

Le fondement de tout dans Fish Redux est Component. Il s'agit d'un objet qui se compose de trois parties: effet, réducteur et vue. Il convient de noter que seule la vue, c'est-à-dire L'effet et le réducteur sont facultatifs; un composant peut fonctionner sans eux. Le composant a également un état actuel.
État
Par exemple, prenez un clicker. Qu'il n'y ait qu'un seul champ dans son état - count, qui indiquera le nombre parfait de clics.
class ClickerState implements Cloneable<ClickerState> { int count = 0; @override ClickerState clone() { return ClickerState() ..count = count; } }
Les États doivent être immuables, immuables. L'immunité aux états peut être facilement maintenue en implémentant l'interface Cloneable. À l'avenir, lorsque vous devrez créer un nouvel état, vous pourrez simplement utiliser la méthode clone()
.
Réducteur
L'essence du réducteur est de répondre à une action en renvoyant un nouvel état. Le réducteur ne doit provoquer aucun effet secondaire.
Nous allons écrire un simple réducteur qui incrémentera le nombre d'un certain nombre à la réception de l'action correspondante (à ce sujet un peu plus bas).
ClickerState clickerReducer(ClickerState state, Action action) {
En outre, ce réducteur pourrait être écrit sous la forme suivante:
Reducer<ClickerState> buildClickerReducer() { asReducer({ Actions.increase: (state, action) => state.clone() ..count = state.count + action.payload,
Action
Action - une classe de la bibliothèque FishRedux qui contient deux champs:
Object type
- Object type
action, généralement un objet enum
dynamic payload
- paramètre d'action, facultatif.
Un exemple:
enum Actions { increase }
Afficher
La logique est prête, il reste à afficher le résultat. View est une fonction qui prend comme paramètres l'état actuel, la répartition, ViewService et renvoie un Widget.
La fonction de répartition est nécessaire pour envoyer des actions: une action dont nous avons décrit la création précédemment.
ViewService contient le BuildContext actuel (de la bibliothèque standard Flutter) et fournit des méthodes pour créer des dépendances, mais à leur sujet plus tard.
Un exemple:
Widget clickerView(ClickerState state, Dispatch dispatch, ViewService viewService) { return RaisedButton( child: Text(state.count.toString()), onPressed: () => dispatch(ActionsCreate.increase(1))
Composant
Nous assemblerons notre composant à partir de tout cela:
class ClickerComponent extends Component<ClickerState> { ClickerComponent() : super( reducer: clickerReducer, view: clickerView, ); }
Comme vous pouvez le voir, l'effet n'est pas utilisé dans notre exemple, car ce n'est pas nécessaire. Un effet est une fonction qui doit effectuer tous les effets secondaires. Mais imaginons un cas dans lequel vous ne pouvez pas vous passer d'effet. Par exemple, cela pourrait être une augmentation de notre nombre d'un nombre aléatoire du service random.org.
Exemple d'implémentation d'effet import 'package:http/http.dart' as http;
La page
Il existe une extension pour le composant appelée Page <T, P>. La page comprend deux champs supplémentaires:
T initState(P params)
- une fonction qui renvoie l'état initial. Sera appelé lorsque la page sera créée.
List<Middleware<T>> middleware
- une liste des middleware - fonctions qui seront appelées avant le réducteur.
Et aussi une méthode:
Widget buildPage(P params)
- qui rassemble la page dans un widget fonctionnel.
Créons la page principale de l'application:
class MainPage extends Page<void, void> { MainPage(): super( initState: (dynamic param) {}, view: (state, dispatch, viewService) => Container(), ); }
Une page étend un composant, ce qui signifie qu'il peut inclure un réducteur, un effet et tout le reste d'un composant standard.
Dans l'exemple, une page vierge a été créée qui n'a ni état, ni réducteurs ni effets. Nous corrigerons cela plus tard.
Tout cela est sous une forme légèrement différente et dans Flutter Redux de Brian Egan, ainsi que dans d'autres implémentations de Redux. Passons à la caractéristique principale de la nouvelle bibliothèque - les dépendances.
Dépendances
Fish Redux vous oblige à définir explicitement les dépendances entre les composants. Si vous souhaitez utiliser un sous-composant dans un composant, vous devez non seulement écrire ces deux composants, mais également créer un connecteur qui sera chargé de convertir un état en un autre. Supposons que nous voulons incorporer un ClickerComponent dans une page MainPage.
Vous devez d'abord ajouter l'état à notre page:
class MainState implements Cloneable<MainState> { ClickerState clicker; @override MainState clone() { return MainState() ..clicker = clicker; } static MainState initState(dynamic params) { return MainState() ..clicker = ClickerState(); } }
Nous pouvons maintenant écrire Connector:
class ClickerConnector extends ConnOp<MainState, ClickerState> { @override ClickerState get(MainState state) => state.clicker;
C’est tout. Tout est prêt pour ajouter notre composant:
class MainPage extends Page<MainState, void> { MainPage(): super( initState: MainState.initState, dependencies: Dependencies( slots: { 'clicker': ClickerComponent().asDependent(ClickerConnector()),
Ainsi, vous pouvez maintenant créer une application de travail complète en ajoutant le code suivant à main.dart
:
void main() => runApp(MyApp()); class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { @override Widget build(BuildContext context) => MaterialApp(home: MainPage().buildPage(null)); }
Tout le code séparé par fichier est disponible ici . Avoir une bonne expérience de développement avec Flutter.