不使用构造函数将StatefulWidget数据传递给State类

7
我成功地通过以下方式将Stateful类变量的值传递给State类的构造函数:

我通过构造函数将Stateful类变量的值传递给了State类:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Demo',
        home: MyHomePage('John', 'Morison'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage(this.fname, this.lname);

  final String fname;
  final String lname;

  @override
  _MyHomePageState createState() => _MyHomePageState(fname, lname);
}

class _MyHomePageState extends State<MyHomePage> {
  _MyHomePageState(this.fname, this.lname);

  final String fname;
  final String lname;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Hello $fname $lname'),
      )
    );
  }
}

这很奇怪,因为有超过两个变量,我必须做很多工作。是否有更好的方法?

3个回答

15

是的,有 widget

From Doc:

  /// The current configuration.
  ///
  /// A [State] object's configuration is the corresponding [StatefulWidget]
  /// instance. This property is initialized by the framework before calling
  /// [initState]. If the parent updates this location in the tree to a new
  /// widget with the same [runtimeType] and [Widget.key] as the current
  /// configuration, the framework will update this property to refer to the new
  /// widget and then call [didUpdateWidget], passing the old configuration as
  /// an argument.
  T get widget => _widget;
  T _widget;

代码应该如下所示:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Demo',
        home: MyHomePage('John', 'Morison'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage(this.fname, this.lname);

  final String fname;
  final String lname;

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

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text('Hello ${widget.fname} ${widget.lname}'),
      )
    );
  }
}

2
我完全不理解这个。你把状态存储在小部件中,而将 UI 构建存储在状态中。这完全与对象命名的方式相反。 - Richard

1
您可以通过widget.访问变量,如状态类中的widget.myVariable。但是,如果要在状态类中更改它们,将变量传递给状态类构造函数是最佳做法。请记住,在父(有状态)类中,变量必须被定义为final,因此如果您想更改这些变量,必须在状态类中定义非final变量,并通过构造函数初始化其值。
  class RecordPage extends StatefulWidget {
      final int myvVariable;
      RecordPage({required this.myvVariable});

      @override
      _RecordPageState createState() => new _RecordPageState(myStateVariable: myvVariable);
  }

class _RecordPageState extends State<RecordPage> {
  int myStateVariable;
  _RecordPageState({required this.myStateVariable});
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          "your initiating variable is " + widget.myvVariable.toString(),
        ),
        Text(
          "your state variable is " + myStateVariable.toString(),
        ),
        InkWell(
          onTap: (){
            setState(() {
              myStateVariable++;
            });
          },
          child: new Container(
            child: Center(
              child: new Text(
                "increase the variable",
              ),
            ),
          ),
        )
      ],
    );
  }
}

0
还有一种解决方案,不使用Flutter Cookbook中提供的构造函数:https://docs.flutter.dev/cookbook/navigation/passing-data 思路是使用RouteSettings和ModalRoute;以下是关键代码部分:
class _TodosScreenState extends State<TodosScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(

// ...            

    onTap: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => const DetailScreen(),
                      // Pass the arguments as part of the RouteSettings. The DetailScreen reads the arguments from these settings.
                      
                      settings: RouteSettings(
                        
                     // widget. is important to access the variable of the stateful class TodosScreen
                        arguments: widget.todos[index],

// ...

class _DetailScreenState extends State<DetailScreen> {
  
  @override
  Widget build(BuildContext context) {
  
    // must be inside build method, as here is the context parameter available 

    final todo = ModalRoute.of(context)!.settings.arguments as Todo;

   // accessing the variable as u wish
   Text(todo.title)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接