Flutter dart 构造器

yzckvree  于 2023-04-27  发布在  Flutter
关注(0)|答案(4)|浏览(150)

在flutter Examples页面中,有一个名为“Sending Data to a new screen”的项目。我在第65行对reguarding构造函数有疑问。
Sending Data to a new screen

// In the constructor, require a Todo
  DetailScreen({Key key, @required this.todo}) : super(key: key);

什么是超级(key:我可以得到整个线路的解释吗?代码在这里....

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

class Todo {
  final String title;
  final String description;

  Todo(this.title, this.description);
}

void main() {
  runApp(MaterialApp(
    title: 'Passing Data',
    home: TodosScreen(
      todos: List.generate(
        20,
            (i) => Todo(
          'Todo $i',
          'A description of what needs to be done for Todo $i',
        ),
      ),
    ),
  ));
}

class TodosScreen extends StatelessWidget {
  final List<Todo> todos;

  TodosScreen({Key key, @required this.todos}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Todos'),
      ),
      body: ListView.builder(
        itemCount: todos.length,
        itemBuilder: (context, index) {
          return ListTile(
            title: Text(todos[index].title),
            // When a user taps on the ListTile, navigate to the DetailScreen.
            // Notice that we're not only creating a DetailScreen, we're
            // also passing the current todo through to it!
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DetailScreen(todo: todos[index]),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

class DetailScreen extends StatelessWidget {
  // Declare a field that holds the Todo
  final Todo todo;

  // In the constructor, require a Todo
  DetailScreen({Key key, @required this.todo}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // Use the Todo to create our UI
    return Scaffold(
      appBar: AppBar(
        title: Text("${todo.title}"),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Text('${todo.description}'),
      ),
    );
  }
}
jqjz2hbq

jqjz2hbq1#

构造函数有两个命名参数。
默认情况下,命名参数是可选的。
@required是Dart分析器识别的注解,如果在构建时调用时未传递,则会产生警告(在运行时没有效果)。
:启动“初始化器列表”,一个逗号分隔的表达式列表,在超类的构造函数之前执行,因此也在构造函数体之前执行。
它通常用于使用Assert检查参数值,并使用计算值初始化final字段。
一个限制是,表达式不能读访问this.(隐式或显式),因为对象初始化在执行超级构造函数之前没有完成。
初始化器中的最后一个元素是对超类的默认构造函数的隐式调用(如果省略),或者对当前类或超类的特定构造函数的调用(如果给定)。
在你的问题的例子中,传递给构造函数的key参数被转发给超类的未命名构造函数的命名参数key

e4yzc0pl

e4yzc0pl2#

这是一个补充Günter Zöchbauer's explanation的示例。它是Align小部件的构造函数。

class Align extends SingleChildRenderObjectWidget {

  // constructor
  const Align({
    Key key,                                                   // named parameter
    this.alignment = Alignment.center,                         // named parameter
    this.widthFactor,                                          // named parameter
    this.heightFactor,                                         // named parameter
    Widget child                                               // named parameter
  }) : assert(alignment != null),                              // initializer list
       assert(widthFactor == null || widthFactor >= 0.0),      // initializer list
       assert(heightFactor == null || heightFactor >= 0.0),    // initializer list
       super(key: key, child: child);                          // initializer list

  // class variables
  final AlignmentGeometry alignment;
  final double widthFactor;
  final double heightFactor;

更多说明:

  • 没有this.前缀的参数是超类的变量。
  • this.开始的参数是在当前类中定义的变量。
nfg76nw0

nfg76nw03#

以下是我对Flutter构造函数的详细理解
一个类中只有一个构造函数,但可以有多个工厂方法。
1.位置参数
这些是传统的参数,它们以与构造函数中定义的相同顺序传递。

MyWidget(String param1, int param2) {
  debugPrint("Positional Optional $param1, $param2");
}

呼叫

MyWidget('Param 1 Passed',2,)

1.命名参数
在flutter中遵循的标准做法,例如我们引用param_name:value

MyWidget(String param1, {int? param2}) {
  debugPrint("Positional Optional $param1, $param2");
}

呼叫

MyWidget('Param 1 Passed',param2: 2,)

1.可选参数
可选参数包含在方括号[ ]

MyWidget(String param1, [int? param2]) {
  debugPrint("Positional Optional, $param1, $param2");
}

现在,由于param 2位于[ ]之间,因此它使param 2成为可选的。因此下面是2种调用它的方法。
方式1:不传递param 2,如果不传递,构造函数将其视为null。

MyWidget('Param 1 Passed',)

方式2:传递两个参数

MyWidget('Param 1 Passed',123)

1.必填参数
当需要强制传递参数时,我们可以使用关键字required沿着{ }

规则required不能与可选参数一起使用,即[ ],显然,如果是必填参数,则不能封装在可选[ ]

MyWidget(String param1, {required int param2}) {
  debugPrint("Positional Optional, $param1, $param2");
}

呼叫

MyWidget('Param 1 Passed', param2: ,123)

1.冒号
冒号主要用于构造函数参数的初始化。

规则:参数不能初始化,本例只能初始化strTxt类中声明的变量。

String strTxt;

MyWidget(String param1, int param2) : strTxt = "Some Value" {
  debugPrint("Positional Optional, $param1, $param2, $strTxt");
}

呼叫

MyWidget('Param 1 Passed', 123)

结果:注意我们在:中设置的debugPrint日志中的“Some Value”
位置可选,参数1通过,123,某个值
1.Body只是大括号内的内容。

1.参数直接赋值
你可能还记得,在Android和其他一些语言中,我们在参数中传递值,然后将其等同于类级别变量。这在Flutter中通过简单地使用this.class_level_var_name完全缩短。它只是将传递的值赋给那个类级别变量。

MyWidget(this.strTxt, int param2) {
  debugPrint("Positional Optional, $strTxt, $param2");
}

呼叫

MyWidget('Param 1 Passed', 123)

结果

Positional Optional, Param 1 Passed, 123

1.nullable ? OR required声明
只有当我们将参数设置为可选[ ]或Named { }时,才需要声明可空,对于定义为普通的参数,不需要required或可空的?
注意param2中的?

MyWidget(this.strTxt, {int? param2}) {
  debugPrint("Positional Optional, $strTxt, $param2, $strTxt");
}

注意事项required

MyWidget(this.strTxt, {required int param2}) {
  debugPrint("Positional Optional, $strTxt, $param2, $strTxt");
}
wkyowqbh

wkyowqbh4#

建造师

class MyApp extends StatefulWidget {
  //create private named constructor
  MyApp._internal();
  // using this private named constructor by creating the instance of it
  // it must be final so it can't be changed.
  static final MyApp instance =
      MyApp._internal(); // Singleton or single instance
  //factory for the class instance
  factory MyApp() => instance; // returns the instance of the class constructor 

  @override
  State<MyApp> createState() => _MyAppState();
}

相关问题