Dart 将函数从窗口小部件触发到状态对象
这是该场景的简化版本:Dart 将函数从窗口小部件触发到状态对象,dart,flutter,Dart,Flutter,这是该场景的简化版本: class ParentWdiegt extends StatelessWidget{ // // floatinActionButton: FloatingActionButtonWidget(onPressed:()=>CustomWidgetState.someMethod(someValue)) // //somewhere in the ParentWidget tree child: CustomWidget() //is stateful } 自定义
class ParentWdiegt extends StatelessWidget{
//
//
floatinActionButton: FloatingActionButtonWidget(onPressed:()=>CustomWidgetState.someMethod(someValue))
//
//somewhere in the ParentWidget tree
child: CustomWidget() //is stateful
}
自定义WidgetState
class CustomWidgetState extends State<CustomWidget>{
//trigger this function when FAB is pressed in parent widget
someMethod(SomeValue) {//}
}
类CustomWidgetState扩展状态{
//在父窗口小部件中按下FAB时触发此功能
someMethod(SomeValue){/}
}
是否有任何方法可以在按下FAB时在要触发的状态对象中公开
someMethod
,而不使用InheritedWidget
?您可以使用GlobalKey
:
// some global place
final customWidgetKey = new GlobalKey<CustomWidgetState>();
而
GlobalKey
允许轻松访问任何小部件的状态;避免它。
小部件不应与其他小部件直接交互。这是颤振的核心原理之一
颤振使用反应式编程代替。小部件通过提交事件相互通信。而不是直接编辑所需的小部件
明显的好处是小部件保持独立。可能有几十个小部件可以使用相同的原理相互通信
我已经举了一个例子,说明如何使两个不同的小部件共享一个公共的可编辑值
如果您想调用方法,则使用相同的原则:在小部件之间共享Listenable
或Stream
。但不使用AnimatedWidget
或StreamBuilder
进行监听。
相反,我们将手动执行侦听(这需要更多的样板文件)来触发自定义函数
下面是一个使用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();
}
}
导入'dart:async';
进口“包装:颤振/材料.省道”;
类ParentWidget扩展了StatefulWidget{
@凌驾
_ParentWidgetState createState()=>\u ParentWidgetState();
}
类_ParentWidgetState扩展状态{
final changeNotifier=new StreamController.broadcast();
@凌驾
无效处置(){
changeNotifier.close();
super.dispose();
}
@凌驾
小部件构建(构建上下文){
返回新列(
儿童:[
新的另一个小部件(
shouldTriggerChange:changeNotifier.stream,
),
新升起的按钮(
子项:新文本(“数据”),
onPressed:()=>changeNotifier.sink.add(null),
)
],
);
}
}
类AnotherWidget扩展StatefulWidget{
最终流应触发更改;
另一个小部件({@required this.shouldTriggerChange});
@凌驾
_另一个WidgetState createState()=>另一个WidgetState();
}
类\u另一个WidgetState扩展状态{
流订阅流订阅;
@凌驾
initState(){
super.initState();
streamSubscription=widget.shouldTriggerChange.listen((\u)=>someMethod());
}
@凌驾
didUpdateWidget(另一个旧小部件){
super.diupdatewidget(旧);
//如果流实例已更改,请订阅新实例
if(widget.shouldTriggerChange!=old.shouldTriggerChange){
streamSubscription.cancel();
streamSubscription=widget.shouldTriggerChange.listen((\u)=>someMethod());
}
}
@凌驾
处置{
super.dispose();
streamSubscription.cancel();
}
void方法(){
打印(“Hello World”);
}
@凌驾
小部件构建(构建上下文){
返回容器();
}
}
在本例中,只要单击由
\u ParentWidgetState
实例化的raised按钮,就会调用另一个小部件的someMethod
尝试存储小部件的状态,然后访问
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;
}
}
类MySFWidget扩展StatefulWidget{
SFWidgetState当前状态;
@凌驾
SFWidgetState createState(){
currState=新的SFWidgetState();
返回状态;
};
}
类SFWidgetState扩展了状态{
int prop;
void方法(){
//做点什么
}
@凌驾
小部件构建(构建上下文){
返回null;
}
}
然后,通过以下方式访问其属性或调用方法:
myWidgetInstance.currState.prop
myWidgetInstance.currState.SomeMethod()
试试看,在状态上调用某个东西真的有意义吗?@RémiRousselet我有一个CustomWidget
有状态的CustomWidgetState
我想把所有状态操作逻辑都保存在CustomWidgetState
中。因此,调用CustomWidgetState
中的状态操作逻辑的一种情况是,在我的问题中,通过按下其他小部件(如ParentWidget
)中的一些按钮来完成的。我这样做的原因是我不想在state
对象之外构建任何状态操作逻辑。如果你有更好的方法来实现这一点,我将非常感谢你的帮助。有意义吗?valueListener可以是clickevent。而且CustomWidgetState
订阅clickEvent to do Stuff看起来很有趣,但据我所知,这只适用于字段,不能触发方法,对吗?通常是个坏主意。首选上下文。对我来说,ancestorStateOfType
ancestorStateOfType
似乎很脆弱,但感谢您指出,我不知道这种方法。这就是我们如何使用导航器获得NatigatorState
。无论如何GlobalKey
在视图中必须是唯一的;这很不方便。特别是在这种情况下,Navigator
是一种更为具体的用例,在这种情况下,可以假定一些层次结构。我没有看到关于特定用例的提示。不确定“特别是在那种情况下”是什么意思-你是指你的Navigator
示例,还是你从我可能遗漏的问题中得出了什么?我的意思是,可能不止一个小部件想要对按钮点击做出反应。但是使用GlobalKey
您需要提前知道整个小部件树是如何工作的。我认为我添加的答案很好地解释了我在这个主题上的思路。这对我不起作用,真的不知道,我基本上是复制和粘贴的。如果一个有状态的小部件初始化
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();
}
}
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;
}
}