J'ai une application Flutter avec 2 onglets: l'un qui gère et reçoit un flux continu de données, l'autre affiche les données au fur et à mesure qu'elles entrent.
Comment passer les données du premier onglet au second? La plupart des articles que je vois concernent la transmission de données entre parent et enfant, et non d'enfant à enfant.
Est-ce que j'utiliserais GlobalKey
? y a-t-il une meilleure option?
Voici la fonction de construction principale:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('some text'),
bottom: TabBar(
tabs: tabs,
controller: _tabController,
),
),
body: TabBarView(
controller: _tabController,
children: [
InputManagment(),
InfiniteListView(),
],
),
);
}
3 réponses
Dans ce cas, il est recommandé d'utiliser InheritedWidget
.
La documentation pour InheritedWidget
est très complète, y compris une vidéo de l'équipe Flutter.
Tout d'abord, vous souhaitez probablement créer une classe contenant les données que vous souhaitez partager.
import 'dart:async';
class MyInheritedWidgetData {
var sharedData;
int someCount;
String someMessage;
final StreamController _streamController = StreamController.broadcast();
Stream get stream => _streamController.stream;
Sink get sink => _streamController.sink;
}
Je viens d'ajouter un tas de variables à cette classe. Vous pouvez le remplir avec ce que vous voulez.
Maintenant, vous voulez également avoir un InheritedWidget
qui contient cette classe de données.
class MyInheritedWidget extends InheritedWidget {
final MyInheritedWidgetData data;
MyInheritedWidget({
Key key,
@required Widget child,
}) : assert(child != null),
data = MyInheritedWidgetData(),
super(key: key, child: child);
static MyInheritedWidgetData of(BuildContext context) => (context.inheritFromWidgetOfExactType(MyInheritedWidget) as MyInheritedWidget).data;
@override
bool updateShouldNotify(MyInheritedWidget old) => false;
}
Vous devez placer ce MyInheritedWidget
en haut de votre arborescence de widgets ou au moins au-dessus du widget parent dont vous avez parlé. Ce qui suit est censé illustrer la hiérarchie nécessaire des widgets.
MyInheritedWidget
TabBarView
InputManagment
InfiniteListView
// in your build function this would be `body: MyInheritedWidget(child: TabBarView(...))`
Désormais, vous pouvez simplement accéder à votre classe de données en utilisant MyInheritedWidget.of(context)
dans l'un de vos widgets enfants.
Vous pouvez envisager d'utiliser des flux pour envoyer et écouter le «flux de données» en continu. Cependant, cela ferait simplement partie de la classe de données. Pour vous donner une idée, j'ai inclus la variable stream dans l'exemple de classe de données. Vous ajouteriez des données à l'aide de MyInheritedWidget.of(context).sink.add(..)
et fourniriez votre flux à un {{ X1}} à l'aide de MyInheritedWidget.of(context).stream
.
Ce ne sont que des exemples pour expliquer ce qui est nécessaire pour partager des données entre widgets. Vous pouvez lire la documentation pour plus d'informations et des cas d'utilisation plus avancés .
Je crois que le fournisseur est la méthode recommandée pour gérer l'état dans Flutter Application et a été présenté à Google IO et est au sommet de la pile pour la gestion de l'état dans le Documentation Flutter sur la gestion des états
- Vidéo de Google / ON Pragmatic State Management in Flutter (Google I / O'19)
service en tant que fournisseur ...
import 'dart:collection';
import 'package:flutter/material.dart';
class Item {
String name;
num price;
Item(this.name, this.price);
}
class CartModel extends ChangeNotifier {
/// Internal, private state of the cart.
final List<Item> _items = [];
/// An unmodifiable view of the items in the cart.
UnmodifiableListView<Item> get items => UnmodifiableListView(_items);
/// The current total price of all items (assuming all items cost $42).
/// int get totalPrice => _items.length * 42;
/// Adds [item] to cart. This is the only way to modify the cart from outside.
void add(Item item) {
_items.add(item);
// This call tells the widgets that are listening to this model to rebuild.
notifyListeners();
}
}
Configuration de l'accès à l'état *
void main() => runApp(
ChangeNotifierProvider<CartModel>(
child: TabBarDemo(),
builder: (BuildContext context) {
return CartModel();
},
),
);
Accès à l'état depuis le niveau supérieur pour afficher le nombre dans le titre de l'onglet
class TabBarDemo extends StatelessWidget {
@override
Widget build(BuildContext context) {
var count = Provider.of<CartModel>(context).items.length;
Accès à l'état depuis le premier onglet lors de l'ajout d'un article au panier
RaisedButton(
child: Text("Add Item"),
onPressed: () async {
final form = _formKey.currentState;
form.save();
if (form.validate()) {
Provider.of<CartModel>(context)
.add(new Item(_name, num.parse(_price)));
} else {
print('validate failed');
}
_formKey.currentState.reset();
})
Voir l'exemple complet ici: https://github.com/aaronksaunders/flutter_simple_tabs, ce code est basé sur l 'Exemple de documentation Flutter
J'ai trouvé cela facile en utilisant un widget avec état bon. Il existe une fonction de première classe sur InputManagement qui prend les données et construit la page d'accueil. Il est important de noter que InputManagement doit appeler cette fonction de manière responsable, car elle reconstruit la page.
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Tabbar Answer',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
TabController tabController;
List<dynamic> data = [];
@override
void initState() {
super.initState();
tabController = TabController(length: 2, vsync: this);
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(title: Text("Tab Delegate")),
body: TabBarView(children: [InputManagement(data: data, delegate: (newData) => setState(() { data = newData; })), InfiniteListView(data: data)], controller: tabController),
bottomNavigationBar: TabBar(controller: tabController, tabs: [Icon(Icons.mail, color: Colors.black), Icon(Icons.view_agenda, color: Colors.black,)])
);
}
class InputManagement extends StatelessWidget {
List<dynamic> data;
void Function(dynamic) delegate;
InputManagement({this.data, this.delegate});
add(dynamic dataItem) {
data.add(dataItem);
delegate(data);
}
@override
Widget build(BuildContext context) => Center(child: FloatingActionButton(onPressed: () => add(data.isEmpty ? 0 : data.last + 1), child: Icon(Icons.add)));
}
class InfiniteListView extends StatelessWidget {
List<dynamic> data = [];
InfiniteListView({this.data});
@override
Widget build(BuildContext context) => ListView.builder(itemBuilder: (context, index) => Container(height: 100, width: MediaQuery.of(context).size.width, alignment: Alignment.center, child: Text(data[index].toString(), style: Theme.of(context).textTheme.title.copyWith(color: Colors.black),)), itemCount: data.length);
}
Questions connexes
Questions liées
De nouvelles questions
flutter
Flutter est un kit de développement de logiciel d'interface utilisateur open source créé par Google. Il est utilisé pour développer des applications pour Android, iOS, Linux, Mac, Windows, Google Fuchsia et le Web à partir d'une seule base de code. Les applications Flutter sont écrites dans le langage Dart.