首页 > 解决方案 > 如何在无状态小部件中将实例字段设置为最终字段?

问题描述

我有Stateless小部件。当用户点击按钮时,我调用计算值的方法。我需要将此值传递到下一页Navigator.push

例如,我有:

class Page1 extends StatelessWidget {
  String value1;
  String value2;

…

child: RaisedButton(
  onPressed: () async {
    await _calculateValue(context);

    Navigator.push(
        context,
        new MaterialPageRoute(
            builder: (BuildContext context) =>
                new Page2(
                  value1: value1,
                  value2: value2,
                )));

…

_calculateValue(BuildContext context) async {

value1 = …
value2 = …

但是当我这样做时flutter analyze会发出警告:

此类(或此类继承自的类)被标记为“@immutable”,但其一个或多个实例字段不是最终的

我不能只声明value1final 因为它会给出错误:

错误:必须初始化最终变量“value1”。

我该如何解决这个问题?

标签: flutterdart

解决方案


据我了解,您正在尝试获取或计算一些值,然后将它们作为参数从一个屏幕传递到另一个屏幕。您可以通过使用具有特殊类的命名路由来完成此操作。您可以使用 检索第二个屏幕上的值ModalRoute.of(context).settings.arguments。对于您的情况,可能是这样的:

import 'package:flutter/material.dart';

class ScreenArguments {
  final String value1;
  final String value2;

  ScreenArguments(this.value1, this.value2);
}

class FirstScreen extends StatelessWidget {
  static const routeName = '/';
  String getSomeValue() {
    return "value";
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: RaisedButton(
        onPressed: () {
          // Consider using loader if getting values takes too much time
          var value1 = getSomeValue();
          var value2 = getSomeValue();

          Navigator.pushNamed(
            context,
            SecondScreen.routeName,
            arguments: ScreenArguments(value1, value2),
          );
        },
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  static const routeName = '/secondScreen';

  @override
  Widget build(BuildContext context) {
    final ScreenArguments args = ModalRoute.of(context).settings.arguments;

    var value1 = args.value1;
    var value2 = args.value2;

    return Container(
      child: Column(
        children: <Widget>[Text(value1), Text(value2)],
      ),
    );
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(initialRoute: FirstScreen.routeName, routes: {
      FirstScreen.routeName: (context) => FirstScreen(),
      SecondScreen.routeName: (context) => SecondScreen(),
    });
  }
}

您可以在此处此处阅读有关命名路线的更多详细信息。


推荐阅读