flutter - 如何从根祖先访问 Flutter 中最新的脚手架?

标签 flutter

我的应用程序在树的根部包含一个 StatefulWidget,它传递其状态以及回调以将状态更改为 InheritedWidget。在其中一个回调中,会创建一个针对 Firebase 的 Firestore 内的文档的监听器来监听更改,然后显示一个 SnackBar 通知用户有关更改的信息。

现在的问题是如何从树根的父级访问当前事件的Scaffold。在根和当前事件的 Scaffold 之间可能有多个其他 Scaffold,具体取决于推送到 Navigator 上的路由数量。但要显示 SnackBar,必须使用最新的一个。

最佳答案

我当前的解决方案可以在以下代码示例中找到。它有效,但我愿意接受更好的想法。我目前不喜欢这个解决方案的是,我需要调用回调来从 didChangeDependencies 中推送当前的 GlobalKey ,因此引入一个成员变量以确保仅调用它Widget 的生命周期中一次,因为无法从 initState 访问 InheritedWidget

除了必须引入成员变量之外,还有其他选择吗?

class MyApp extends StatefulWidget {
  final Firestore firestore;

  const MyApp(this.firestore);

  @override
  State<StatefulWidget> createState() {
    return new MyAppState();
  }
}

class MyAppState extends State<MyApp> {
  void addDocumentListener(DocumentReference ref) {
    ref.snapshots.listen((snapshot) {
      _scaffoldKeys.last.currentState.showSnackBar(new SnackBar(content: new Text("Test")));
    });
  }

  var _scaffoldKeys = new Queue<GlobalKey<ScaffoldState>>();
  void pushScaffoldKey(GlobalKey<ScaffoldState> key) {
    _scaffoldKeys.addLast(key);
  }
  GlobalKey<ScaffoldState> popScaffoldKey() {
    return _scaffoldKeys.removeLast();
  }

  @override
  Widget build(BuildContext context) {
    return new MyInheritedWidget(addDocumentListener, pushScaffoldKey, popScaffoldKey, new MaterialApp(home: new HomePage()));
  }
}

typedef VoidDocumentReferenceCallback(DocumentReference ref);
typedef VoidGlobalKeyScaffoldStateCallback(GlobalKey<ScaffoldState> key);
typedef GlobalKey<ScaffoldState> GlobalKeyScaffoldStateCallback();

class MyInheritedWidget extends InheritedWidget {
  final VoidDocumentReferenceCallback addDocumentListener;
  final VoidGlobalKeyScaffoldStateCallback pushScaffoldKey;
  final GlobalKeyScaffoldStateCallback popScaffoldKey;

  const MyInheritedWidget(this.addDocumentListener, this.pushScaffoldKey, this.popScaffoldKey, Widget child) : super(child: child);

  @override
  bool updateShouldNotify(InheritedWidget oldWidget) {
    return false;
  }

  static MyInheritedWidget of(BuildContext context) {
    return context.inheritFromWidgetOfExactType(MyInheritedWidget);
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new CustomScaffold(
      appBar: new AppBar(
        title: new Text("Home Page"),
        actions: <Widget>[
          new IconButton(icon: const Icon(Icons.settings), onPressed: () {
            Navigator.of(context).push(new MaterialPageRoute(builder: (context) {
              // go to another page with a CustomScaffold
            }));
          })
        ],
      ),
      body: new Center(
        child: new RaisedButton(onPressed: () {
          MyInheritedWidget.of(context).addDocumentListener(ref);
        }, child: new Text("add listener")),
      ),
    );
  }
}

class CustomScaffold extends StatefulWidget {
  final AppBar appBar;
  final Widget body;

  const CustomScaffold({this.appBar, this.body});

  @override
  State<StatefulWidget> createState() {
    return new CustomScaffoldState();
  }
}

class CustomScaffoldState extends State<CustomScaffold> {
  final _key = new GlobalKey<ScaffoldState>();

  bool _keyInitialized = false;

  @override
  didChangeDependencies() {
    if (!_keyInitialized) {
      MyInheritedWidget.of(context).pushScaffoldKey(_key);
      _keyInitialized = true;
    }
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    var scaffold = new Scaffold(
      key: _key,
      appBar: widget.appBar,
      body: widget.body,
    );

    return new WillPopScope(child: scaffold, onWillPop: () {
      MyInheritedWidget.of(context).popScaffoldKey();
      return new Future.value(true);
    });
  }
}

关于flutter - 如何从根祖先访问 Flutter 中最新的脚手架?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49967710/

相关文章:

Flutter:这需要启用 'non-nullable' 语言功能

Flutter 不同的创建状态方式有什么区别?

flutter - 在 future builder 中使用列表构建器时 flutter 显示错误

android - Flutter - 拍照

flutter - 停止在 flutter 中收听 Cloud Firestore 中的快照更新

rest - 确保在后台处理 flutter 应用程序中的 REST 调用

java - Gradle任务assembleDebug失败,退出代码为1 ERROR?

flutter - flutter 中的盒子阴影没有出现

dart - 如何在事件之上创建一个透明的全屏对话框 - Flutter

ios - Firebase 上 iOS 的 Flutter 集成测试?