触发从窗口小部件到状态对象的函数

时间:2018-06-07 05:54:23

标签: dart flutter

这是该场景的简化版本:

class ParentWdiegt extends StatelessWidget{
//
//
floatinActionButton: FloatingActionButtonWidget(onPressed:()=>CustomWidgetState.someMethod(someValue))
//
//somewhere in the ParentWidget tree
child: CustomWidget() //is stateful
}

CustomWidgetState

class CustomWidgetState extends State<CustomWidget>{
//trigger this function when FAB is pressed in parent widget
someMethod(SomeValue) {//}
}

在没有使用someMethod的情况下按下FAB时,有什么方法可以在要触发的状态对象中公开InheritedWidget吗?

3 个答案:

答案 0 :(得分:19)

虽然GlobalKey允许轻松访问任何小部件的状态;躲开它。 窗口小部件应该直接与其他窗口小部件交互。这是Flutter的核心原则之一。

Flutter使用反应式编程。小部件通过提交事件与彼此通信的位置。而不是直接编辑所需的小部件。

显而易见的好处是小部件保持独立。并且可能有数十个小部件可以使用相同的原则相互通信。

我已经就如何使两个不同的小部件共享一个共同的可编辑值做了一个示例here

如果您想要调用方法,则使用相同的原则:小部件之间共享ListenableStream。但是没有使用AnimatedWidgetStreamBuilder进行收听。 相反,我们将手动进行监听(这需要更多的样板)来触发自定义功能。

以下是使用Stream的示例。

import 'dart:async';
import 'package:flutter/material.dart';

class ParentWidget extends StatefulWidget {
  @override
  _ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  final changeNotifier = new StreamController.broadcast();

  @override
  void dispose() {
    changeNotifier.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Column(
      children: <Widget>[
        new AnotherWidget(
          shouldTriggerChange: changeNotifier.stream,
        ),
        new RaisedButton(
          child: new Text("data"),
          onPressed: () => changeNotifier.sink.add(null),
        )
      ],
    );
  }
}

class AnotherWidget extends StatefulWidget {
  final Stream shouldTriggerChange;

  AnotherWidget({@required this.shouldTriggerChange});

  @override
  _AnotherWidgetState createState() => _AnotherWidgetState();
}

class _AnotherWidgetState extends State<AnotherWidget> {
  StreamSubscription streamSubscription;

  @override
  initState() {
    super.initState();
    streamSubscription = widget.shouldTriggerChange.listen((_) => someMethod());
  }

  @override
  didUpdateWidget(AnotherWidget old) {
    super.didUpdateWidget(old);
    // in case the stream instance changed, subscribe to the new one
    if (widget.shouldTriggerChange != old.shouldTriggerChange) {
      streamSubscription.cancel();
      streamSubscription = widget.shouldTriggerChange.listen((_) => someMethod());
    }
  }

  @override
  dispose() {
    super.dispose();
    streamSubscription.cancel();
  }

  void someMethod() {
    print('Hello World');
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

在此示例中,只要执行someMethod实例化的AnotherWidget上的点击,就会调用RaisedButton _ParentWidgetState

答案 1 :(得分:2)

您可以使用GlobalKey

// some global place
final customWidgetKey = new GlobalKey<CustomWidgetState>();

...

  // import the file with "customWidgetKey"

  new CustomWidget(key: customWidetKey, ...)

...

  // import the file with "customWidgetKey"

  floatinActionButton: FloatingActionButtonWidget(
      onPressed: ()=>customWidgetKey.currentState.someMethod(someValue))

答案 2 :(得分:-1)

尝试存储小部件的状态,然后访问

class MySFWidget extends StatefulWidget {
  SFWidgetState currState;

  @override
  SFWidgetState createState(){
    currState = new SFWidgetState();
    return currState;
  };

}

class SFWidgetState extends State<MySFWidget> {

  int prop;

  void SomeMethod(){
    // DO Something
  }

  @override
  Widget build(BuildContext context) {
    return null;
  }

}

然后,通过以下方式访问其属性或调用方法:

myWidgetInstance.currState.prop

myWidgetInstance.currState.SomeMethod()