I'm using Flutter. I have a simple app with 3 tabs. There is a RefreshIndicator in each tab with a ListView. The rows are built in another method. This is the code:
@override Widget build(BuildContext context) { final GlobalKey<RefreshIndicatorState> _RIKey1 = new GlobalKey<RefreshIndicatorState>(); final GlobalKey<RefreshIndicatorState> _RIKey2 = new GlobalKey<RefreshIndicatorState>(); final GlobalKey<RefreshIndicatorState> _RIKey3 = new GlobalKey<RefreshIndicatorState>(); debugPrint(_RIKey1.toString()); debugPrint(_RIKey2.toString()); debugPrint(_RIKey3.toString()); return new Scaffold( body: new DefaultTabController( length: 3, child: new Scaffold( appBar: new AppBar( bottom: new TabBar( tabs: [ new Tab(icon: new Icon(Icons.view_list)), new Tab(icon: new Icon(Icons.hotel)), new Tab(icon: new Icon(Icons.assessment)), ], ), title: new Text('Data'), ), body: new TabBarView( children: [ new RefreshIndicator( key: _RIKey1, onRefresh: _actualizoData, child: new ListView.builder( padding: new EdgeInsets.only(top: 5.0), itemCount: linea_reservas.length * 2, itemBuilder: (BuildContext context, int position) { if (position.isOdd) return new Divider(); final index = position ~/ 2; return _buildRow(index); }), ), new RefreshIndicator( key: _RIKey2, onRefresh: _actualizoData, child: new ListView.builder( padding: new EdgeInsets.only(top: 8.0), itemCount: linea_inouthouse.length * 2, itemBuilder: (BuildContext context, int position) { if (position.isOdd) return new Divider(); final index = position ~/ 2; return _buildRowInOutHouse(index); }), ), new RefreshIndicator( key: _RIKey3, onRefresh: _actualizoData, child: new ListView.builder( padding: new EdgeInsets.only(top: 5.0), itemCount: linea_ocupacion.length * 2, itemBuilder: (BuildContext context, int position) { if (position.isOdd) return new Divider(); final index = position ~/ 2; return _buildRowOcupacion(index); }), ), ], ), ), ), ); }
I'd added the debugPrints and the output are 6 lines, instead of 3.
I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#4d76c] I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#59b9e] I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#2c88b] I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#7bd42] I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#1c984] I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#dbe20]
the app works, but after changing tabs a few times, it crashes with this error:
I/flutter ( 5252): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════ I/flutter ( 5252): The following assertion was thrown building NotificationListener<KeepAliveNotification>: I/flutter ( 5252): Multiple widgets used the same GlobalKey. I/flutter ( 5252): The key [LabeledGlobalKey<RefreshIndicatorState>#7bd42] was used by multiple widgets. The parents of I/flutter ( 5252): those widgets were: I/flutter ( 5252): - RepaintBoundary-[<[LabeledGlobalKey<RefreshIndicatorState>#7bd42]>](renderObject: I/flutter ( 5252): RenderRepaintBoundary#60a4a DETACHED) I/flutter ( 5252): - RepaintBoundary-[<[LabeledGlobalKey<RefreshIndicatorState>#7bd42]>](renderObject: I/flutter ( 5252): RenderRepaintBoundary#c8cdb NEEDS-LAYOUT NEEDS-PAINT) I/flutter ( 5252): A GlobalKey can only be specified on one widget at a time in the widget tree.
The keys are generated in the Build method, so, I don't understand why the Multiple widgets used the same GlobalKey
error
Why the key is generated again, and why it's not unique? I'm not talking of a thousand intents, the error appears after changing between tabs 4 or 5 times. Thank you for any help.
They are using the same key because when you create the FormBuilderWrapper you pass the key to it, and then inside you return a formBuilder passing the same key you gave the FormBuilderWrapper .
Could you create your keys "by hand" and use static/constant values? e.g. ...
import 'package:flutter/widgets.dart'; class RIKeys { static final riKey1 = const Key('__RIKEY1__'); static final riKey2 = const Key('__RIKEY2__'); static final riKey3 = const Key('__RIKEY3__'); }
then in ...
body: new TabBarView( children: [ new RefreshIndicator(new RefreshIndicator( // Use the Manual Static Value instead ... key: RIKeys.riKey1, onRefresh: _actualizoData, child: new ListView.builder( padding: new EdgeInsets.only(top: 5.0), itemCount: linea_reservas.length * 2, itemBuilder: (BuildContext context, int position) { if (position.isOdd) return new Divider(); final index = position ~/ 2; return _buildRow(index); }), ),
I have done this in a similar situation with some success ... especially with redux or other similar patterns ...
this code worked for me ... I want to create a List of Form Key ...
just Changing GlobalKey
with GlobalObjectKey
like below.
final List<GlobalObjectKey<FormState>> formKeyList = List.generate(10, (index) => GlobalObjectKey<FormState>(index));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With