如何在Flutter中从另一个StatefulWidget设置/更新StatefulWidget的状态?

10 浏览
0 Comments

如何在Flutter中从另一个StatefulWidget设置/更新StatefulWidget的状态?

例如,在下面的代码中,加号按钮可以更新文本,但是减号按钮不能。

但是,如果我们按下FloatingActionButton,状态会被刷新。

减号按钮改变了变量的值,但没有更新父部件的状态。

这是代码...

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {

@override

Widget build(BuildContext context) {

return new MaterialApp(

title: 'Flutter Demo',

theme: new ThemeData(

primarySwatch: Colors.blue,

),

home: new MyHomePage(title: 'Flutter Demo Home Page'),

);

}

}

int number;

EdgeInsets globalMargin = const EdgeInsets.symmetric(horizontal: 20.0, vertical: 20.0);

TextStyle textStyle = const TextStyle(

fontSize: 100.0,

color: Colors.black,

);

class MyHomePage extends StatefulWidget {

MyHomePage({Key key, this.title}) : super(key: key);

final String title;

@override

_MyHomePageState createState() => new _MyHomePageState();

}

class _MyHomePageState extends State {

@override

void initState() {

super.initState();

number = number ?? 0;

}

@override

Widget build(BuildContext context) {

return new Scaffold(

appBar: new AppBar(

title: new Text(widget.title),

),

body: new Column(

children: [

new Text(

number.toString(),

style: textStyle,

),

new GridView.count(

crossAxisCount: 2,

shrinkWrap: true,

scrollDirection: Axis.vertical,

children: [

new InkResponse(

child: new Container(

margin: globalMargin,

color: Colors.green,

child: new Center(

child: new Text(

"+",

style: textStyle,

),

)),

onTap: () {

setState(() {

number = number + 1;

});

},

),

new Sub(),

],

),

],

),

floatingActionButton: new FloatingActionButton(

onPressed: () {

setState(() {});

},

child: new Icon(Icons.update),

),

);

}

}

class Sub extends StatefulWidget {

@override

_SubState createState() => new _SubState();

}

class _SubState extends State {

@override

Widget build(BuildContext context) {

return new InkResponse(

child: new Container(

margin: globalMargin,

color: Colors.red,

child: new Center(

child: new Text(

"-",

style: textStyle,

),

)),

onTap: () {

setState(() {

number = number - 1;

});

},

);

}

}

0
0 Comments

在Flutter中,有时候我们需要在一个StatefulWidget中的子部件中调用另一个StatefulWidget的方法,或者在父部件中调用子部件的方法。这篇文章将介绍如何实现这样的功能。

在给出的代码示例中,有一个父部件ParentPage和一个子部件ChildPage。父部件中有一个按钮,点击按钮时会调用子部件的方法;子部件中也有一个按钮,点击按钮时会调用父部件的方法。

为了实现在父部件中调用子部件的方法,我们可以使用GlobalKey来获取子部件的状态。在这个示例中,ParentPage中定义了一个名为_key的GlobalKey<ChildPageState>变量,然后将它传递给ChildPage的key属性。这样,在父部件中就可以通过_key.currentState来获取子部件的状态,进而调用子部件的方法。

为了在子部件中调用父部件的方法,我们可以在子部件中定义一个VoidCallback类型的属性function,该属性会在子部件中的按钮点击事件中调用。然后,将父部件中的方法作为参数传递给子部件的function属性。

当然,我们也可以通过使用GlobalKey在其他类中调用_ChildPageState。只需将_ChildPageState的私有标识符_去掉即可。

在处理多个子部件的情况下,我们可以为每个子部件创建一个对应的GlobalKey。但需要注意的是,使用GlobalKey可能会在设备上有一定的性能开销,因此需要谨慎使用。

总结起来,要实现在Flutter中从一个StatefulWidget中的子部件调用另一个StatefulWidget的方法,或者在父部件中调用子部件的方法,我们可以使用GlobalKey来获取子部件的状态,并通过该状态调用相应的方法。此外,我们还可以在子部件中定义一个属性,将父部件的方法传递给子部件,在子部件中调用该方法。需要注意的是,GlobalKey的使用可能会带来一定的性能开销,需要慎重考虑。

0
0 Comments

如何从Flutter中的其他StatefulWidget设置/更新State?

问题的原因是我们想要在一个StatefulWidget中更新另一个StatefulWidget的状态。以下是一些旧的/不推荐/失败的解决方案:

1. 解决方案1:创建一个_MyHomePageState的全局实例,在_SubState中使用此实例作为_myHomePageState.setState

2. 解决方案2:不需要创建全局实例,只需将父实例传递给子小部件。

3. 解决方案3:从父小部件传递回调到子小部件,以从子小部件更新父小部件的状态。

最佳解决方案是使用包stream_mixin。以下是解决方案的代码:

class Counter with StreamMixin {

Counter._();

static Counter instance = Counter._();

increment() {

update((lastUpdate ?? 0) + 1);

}

decrement() {

update((lastUpdate ?? 0) - 1);

}

}

class MyHomePage extends StatelessWidget {

const MyHomePage({Key key});

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

title: const Text('SO Help'),

),

body: Column(

children: [

StreamBuilder(

initialData: 0,

stream: Counter.instance.onChange,

builder: (context, snapshot) {

return Text(snapshot.data.toString());

},

),

GridView.count(

crossAxisCount: 2,

shrinkWrap: true,

scrollDirection: Axis.vertical,

children: [

InkResponse(

onTap: Counter.instance.increment,

child: const Text("+"),

),

const Sub(),

],

),

],

),

);

}

}

class Sub extends StatelessWidget {

const Sub({Key key});

Widget build(BuildContext context) {

return InkResponse(

onTap: Counter.instance.decrement,

child: const Text("-"),

);

}

}

值得注意的是:

1. 我使用的是StatelessWidget,这将提高性能。

2. 我使用StreamBuilder,这将只更新StreamBuilder中的Text小部件,而不像setState()会更新整个应用程序。

3. 逻辑与UI分开。

这是一个有效的解决方案,但不是最佳的。至少可以使用context.ancestorStateOfType等方法来改进。

以上就是从其他StatefulWidget设置/更新State的问题的原因和解决方法。

0
0 Comments

在Flutter中,如果想要从一个StatefulWidget的子组件更新另一个StatefulWidget的状态,可以通过以下方法实现:

1. 在子组件中添加一个回调函数参数:

class ChildWidget extends StatefulWidget {

final Function() notifyParent;

ChildWidget({Key key, this.notifyParent}) : super(key: key);

}

2. 在父组件中创建一个用于子组件回调的函数:

refresh() {

setState(() {});

}

3. 在父组件中将父组件的函数传递给子组件:

new ChildWidget(notifyParent: refresh);

4. 在子组件中调用父组件的函数:

widget.notifyParent();

这样就可以从父组件更新子组件的状态了。

如果需要从父组件更新一个有状态的子组件,可以在父组件中存储子组件的引用,并调用子组件的公共方法来更新状态。

如果需要从子组件向父组件传递参数,可以在父组件中定义一个带参数的回调函数,并在子组件中调用该函数并传递参数:

refresh(argument1, argument2) {

setState(() {});

}

widget.notifyParent(1, 2);

以上是一种解决方案,但并不是官方团队提供的解决方法。

如果对此有更好的解决方案,可以在问题的回答中添加新的答案,或者向Flutter团队提出建议,在GitHub上开启一个问题(issue)。如果不知道如何操作,也可以请求帮助,有人会为你完成这个操作。

对于那些想要向子组件传递值的人,可以在父组件中创建一个ValueNotifier,并将其传递给子组件。在子组件中,可以利用ValueListenableBuilder来构建布局。

如果还有问题,请在Stack Overflow上更新问题。

0