将数据传递给有状态的小部件

Moj*_*iee 66 dart flutter

我想知道在创建数据时,将数据传递给有状态小部件的最佳/最佳性能是什么.

我见过的两种风格是:

class ServerInfo extends StatefulWidget {

  Server _server;

  ServerInfo(Server server) {
    this._server = server;
  }

  @override
    State<StatefulWidget> createState() => new _ServerInfoState(_server);
}

class _ServerInfoState extends State<ServerInfo> {
  Server _server;

  _ServerInfoState(Server server) {
    this._server = server;
  }
}
Run Code Online (Sandbox Code Playgroud)

这种方法保持的值都在ServerInfo_ServerInfoState,这似乎有点浪费.

另一种方法是使用widget._server:

class ServerInfo extends StatefulWidget {

  Server _server;

  ServerInfo(Server server) {
    this._server = server;
  }

  @override
    State<StatefulWidget> createState() => new _ServerInfoState();
}

class _ServerInfoState extends State<ServerInfo> {
  @override
    Widget build(BuildContext context) {
      widget._server = "10"; // Do something we the server value
      return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

这似乎有点倒退,因为状态不再存储在_ServerInfoSate窗口小部件中而是存储在窗口小部件中.

这是最好的做法吗?

Rém*_*let 140

不要将参数传递给State使用它的构造函数.您应该只使用这些this.widget.myField.

编辑构造函数不仅需要大量的手工操作; 它没带任何东西.没有理由复制所有的字段Widget.

编辑:

这是一个例子

class MyStateful extends StatefulWidget {
  final String foo;

  const MyStateful({Key key, this.foo}): super(key: key);

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

class _MyStatefulState extends State<MyStateful> {
  @override
  Widget build(BuildContext context) {
    return Text(widget.foo);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 进一步注释,通过构造函数传递给State对象的任何内容都不会得到更新! (11认同)
  • @Rexford`State`已经可以使用`widget`字段访问`Stateful`的所有属性. (5认同)
  • 我在这里也听不懂这句话。“不要使用其构造函数将参数传递给State”。那么如何将参数传递给State? (4认同)
  • @RémiRousselet如果我想使用foo来预填充文本字段,并且仍然允许用户对其进行编辑,该怎么办。我还应该在状态中添加另一个foo属性吗? (3认同)
  • @user6638204您可以在状态中创建另一个 foo 属性,并在状态上覆盖 `void initState()` 以设置初始值。检查此[线程](https://groups.google.com/d/msg/flutter-dev/zRnFQU3iZZs/ThAfrMfyBwAJ)选项 C 作为示例。 (3认同)
  • 另一方面,将所有对象保留在小部件而不是状态中似乎很奇怪。 (3认同)

San*_*inh 49

最好的方法是不要使用它的构造函数将参数传递给 State 类。您可以使用widget.myField.

例如

class UserData extends StatefulWidget {
  final String clientName;
  final int clientID;
  const UserData(this.clientName,this.clientID);

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

class UserDataState extends State<UserData> {
  @override
  Widget build(BuildContext context) {
    // Here you direct access using widget
    return Text(widget.clientName); 
  }
}
Run Code Online (Sandbox Code Playgroud)

当您导航屏幕时传递您的数据:

 Navigator.of(context).push(MaterialPageRoute(builder: (context) => UserData("WonderClientName",132)));
Run Code Online (Sandbox Code Playgroud)


Dak*_*hah 7

用于传递初始值(不向构造函数传递任何内容)

class MyStateful extends StatefulWidget {
  final String foo;

  const MyStateful({Key key, this.foo}): super(key: key);

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

class _MyStatefulState extends State<MyStateful> {
  @override
  void initState(){
    super.initState();
    // you can use this.widget.foo here
  }

  @override
  Widget build(BuildContext context) {
    return Text(foo);
  }
}
Run Code Online (Sandbox Code Playgroud)


Nic*_*ard 5

如果您要传递初始值并且以后仍然能够在状态中更新它们,则以@RémiRousselet的anwser为基础,并针对@ user6638204的问题,给出另一个答案:

class MyStateful extends StatefulWidget {
  final String foo;

  const MyStateful({Key key, this.foo}): super(key: key);

  @override
  _MyStatefulState createState() => _MyStatefulState(foo: this.foo);
}

class _MyStatefulState extends State<MyStateful> {
  String foo;

  _MyStatefulState({this.foo});

  @override
  Widget build(BuildContext context) {
    return Text(foo);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我们可以直接使用initState做类似foo = widget.foo的操作,不需要传递给构造函数 (4认同)

Max*_*lin 5

Flutter 的有状态 widgets API 有点尴尬:将数据存储在 Widget 中,以便在对象build()中的方法中访问它State。如果您不想使用一些更大的状态管理选项(Provider、BLoC),请使用 flutter_hooks ( https:// pub.dev/packages/flutter_hooks) - 它是 s 的更好、更干净的替代品SatefullWidget

class Counter extends HookWidget {
  final int _initialCount;

  Counter(this._initialCount = 0);
  
  @override
  Widget build(BuildContext context) {
    final counter = useState(_initialCount);

    return GestureDetector(
      // automatically triggers a rebuild of Counter widget
      onTap: () => counter.value++,
      child: Text(counter.value.toString()),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)