Why Flutter GlobalKey's currentState is NULL when accessed from other file
That is due to how dart import works.
In dart, there is two way to import sources :
- import './relative/path.dart'
- import 'myApp/absolute/path.dart'
The thing is, they are not compatible with each others. Both these imports will have a different runtimeType
.
But how is that a problem ? I never used relative import
That's a problem, because in some situations you implicitly use "relative imports" : When using a class A defined in foo.dart
inside foo.dart
.
So, how do I solve the problem ?
There are multiple solutions :
- Have everything related to your class
App
should be inside the same file. (That's the recommended thing in dart) - Extract
App
into it's own file. And import it everywhere using absolute imports. - Don't use
GlobalKey
to begin with. As your use case is definitely in the scope ofInheritedWidget
.
Edmund Tam
Updated on December 04, 2022Comments
-
Edmund Tam over 1 year
Here's my code:
import 'package:flutter/material.dart'; void main() { runApp(new MyStatefulApp(key: App.appStateKey)); } /// Part [A]. No difference when appStateKey is defined as variable. class App { static final GlobalKey<MyAppState> appStateKey = new GlobalKey<MyAppState>(); } /// Part [B] class MyStatefulApp extends StatefulWidget { MyStatefulApp({Key key}) :super(key: key); @override MyAppState createState() => new MyAppState(); } class MyAppState extends State<MyStatefulApp> { int _counter = 0; add() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return new MaterialApp( title: "App", theme: new ThemeData( primarySwatch: _counter % 2 == 0 ? Colors.blue : Colors.red, ), home: new MyHomePage(), ); } } /// Part [C] class MyHomePage extends StatefulWidget { MyHomePage({Key key}) : super(key: key); @override _MyHomePageState createState() => new _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar(title: new Text("Main"), ), body: new FlutterLogo(), floatingActionButton: new FloatingActionButton( onPressed: () { App.appStateKey.currentState.add(); // (X) }, tooltip: "Trigger color change", child: new Icon(Icons.add), ), ); } }
In the code above, when the FAB is clicked,
MaterialApp
should rebuild, and the primary color will switch between blue and red.In fact, the code worked, until I attempted to split the portions of the code to different files.
App.appStateKey.currentState
on line (X) will be becomenull
when:- Part A (The
App
class, or the variable) is moved to another file; - Part C (
MyHomePage
and_MyHomePageState
) is moved to another file; - Part A and C are moved to another file
So it looks like the
GlobalKey.currentState
only work when everything involving this GlobalKey is in the same file.The doc only states that
currentState
will be null when(1) there is no widget in the tree that matches this global key, (2) that widget is not a StatefulWidget, or the associated State object is not a subtype of T.
It doesn't state that everything has to be in the same file.Breaking classes into files may not be "the Dart way", but I assume it should work anyhow (they're all public). So this puzzles me, and I suspect if I have stumbled upon certain Flutter feature that I am not aware of. Thanks.
- Part A (The
-
Edmund Tam about 6 yearsThanks for pointing me to this direction. But my actual problem is due to the use of the "package:" directive to import local package files (or to be exact, the Flutter plugin in Android Studio did this for me). I have to use relative import, so that Dart won't see it as another package. I got the answer after asking in the Flutter discussion forum. And yes, using GlobalKey isn't a good idea for this particular case. I ended up passing a method callback to the child widget.
-
Rémi Rousselet about 6 yearsThat's exactly what I said here :)
-
Rémi Rousselet about 6 yearsI made a better explanation of this "package" problem here
-
Rémi Rousselet about 6 yearsAnd discussed a lot about it on flutter gittter