在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;
}
}

这个方法在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;
}
}

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

这方面有最佳实践吗?

166439 次浏览
不要使用State的构造函数将参数传递给它。 只能使用this.widget.myField访问参数

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

编辑:

这里有一个例子:

class ServerIpText extends StatefulWidget {
final String serverIP;


const ServerIpText ({ Key? key, this.serverIP }): super(key: key);


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


class _ServerIpTextState extends State<ServerIpText> {
@override
Widget build(BuildContext context) {
return Text(widget.serverIP);
}
}


class AnotherClass extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: ServerIpText(serverIP: "127.0.0.1")
);
}
}

另一个答案,建立在@RémiRousselet的回答器和@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);
}
}

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

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);
}
}

最好的方法是不使用State类的构造函数将参数传递给State类。你可以使用widget.myField在State类中轻松访问。

例如

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);
}
}

在导航屏幕时传递数据: < br >

 Navigator.of(context).push(MaterialPageRoute(builder: (context) => UserData("WonderClientName",132)));

@Rémi Rousselet, @Sanjayrajsinh, @Daksh Shah也更好。但我也定义了这是从起点开始的。哪个参数就是哪个值

   import 'package:flutter/material.dart';
    

    

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

class MyApp extends StatelessWidget {
String name = "Flutter Demo";
String description = "This is Demo Application";
    

@override
Widget build(BuildContext context) {
return MaterialApp(
home: MainActivity(
appName: name,
appDescription: description,
),
);
}
}
    

class MainActivity extends StatefulWidget {
MainActivity({Key key, this.appName, this.appDescription}) : super(key: key);
var appName;
var appDescription;
    

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

class _MainActivityState extends State<MainActivity> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.appName),
),
body: Scaffold(
body: Center(
child: Text(widget.appDescription),
),
),
);
}
}

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

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()),
);
}
}

要将data传递给有状态小部件,首先,创建两个页面。现在从第一页打开第二页并传递数据。

class PageTwo extends StatefulWidget {
final String title;
final String name;


PageTwo ({ this.title, this.name });


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


class PageTwoStateState extends State<PageTwo> {
@override
Widget build(BuildContext context) {
return Text(
widget.title,
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w700),
),
}
}


class PageOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialButton(
text: "Open PageTwo",
onPressed: () {
var destination = ServicePage(
title: '<Page Title>',
provider: '<Page Name>',
);
Navigator.push(context,
MaterialPageRoute(builder: (context) => destination));
},);
}
}