首页 > 解决方案 > 无法将命名参数传递给颤振中的路由

问题描述

我正在做一个来自 Udemy 课程的示例应用程序,在试验 NamedRoute 时,我在将参数传递给路由时遇到了问题。

运行时,单击按钮导航到下一条路线后,我得到输出:

I/flutter ( 7056): bmi:20.7 inter:You are normal. Excellent.

但是参数似乎没有传递给路由,因为我得到了异常:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building ResultsPage(dirty):
A non-null String must be provided to a Text widget.
'package:flutter/src/widgets/text.dart':
Failed assertion: line 285 pos 10: 'data != null'

错误在 results_page 中的以下行中:

Text(bmi, style:TextStyle(fontSize: 100, fontWeight: FontWeight.bold),)

这表明 results_page 没有得到正在传递的参数 bmi 。

Dart 分析显示以下问题: 在 main.dart 中:

warning: The parameter 'interpretation' is required. . (missing_required_param at [bmi_calculator] lib/main.dart:22)
warning: The parameter 'bmi' is required. . (missing_required_param at [bmi_calculator] lib/main.dart:22)

这些指向 main.dart 中的以下行:

routes: {
        '/': (context) => InputPage(),
        '/results': (context) => ResultsPage(),
      },

我的 main.dart:

import 'package:flutter/material.dart';
import 'input_page.dart';
import 'results_page.dart';
void main() => runApp(BMICalculator());
class BMICalculator extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
          primaryColor: Color(0xFF0A0C22),
          accentColor: Colors.purple,
          scaffoldBackgroundColor: Color(0xFF0A0C22),
          textTheme: TextTheme(
              body1: TextStyle(
            color: Colors.white,
          ))),
      initialRoute: '/',
      routes: {
        '/': (context) => InputPage(),
        '/results': (context) => ResultsPage(),
      },
    );
  }
}

input_page.dart:

class InputPage extends StatefulWidget {
  @override
  _InputPageState createState() => _InputPageState();
}
enum Gender { male, female, other }
class _InputPageState extends State<InputPage> {
  int heightVal = kmaxHeight;
  int weightVal = kstartWeight;
  int ageVal = kstartAge;

  Gender selectedGender;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('BMI CALCULATOR'),
      ),
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          Expanded(
            child: Row(
              children: <Widget>[
                Expanded(
                  child: ReusableCard(
                    onPress: () {
                      setState(() {
                        selectedGender = selectedGender == Gender.male
                            ? Gender.other
                            : Gender.male;
                      });
                    },
                    colour: selectedGender == Gender.male
                        ? kactiveCardColor
                        : kinactiveCardColor,
                    cardChild: IconContent(
                      icon: FontAwesomeIcons.mars,
                      label: "MALE",
                    ),
                  ),
                ),
                Expanded(
                    child: ReusableCard(
                  onPress: () {
                    setState(() {
                      selectedGender = selectedGender == Gender.female
                          ? Gender.other
                          : Gender.female;
                    });
                  },
                  colour: selectedGender == Gender.female
                      ? kactiveCardColor
                      : kinactiveCardColor,
                  cardChild: IconContent(
                    icon: FontAwesomeIcons.venus,
                    label: "FEMALE",
                  ),
                )),
              ],
            ),
          ),
          Expanded(
            child: ReusableCard(
              colour: kactiveCardColor,
              cardChild: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'HEIGHT',
                    style: TextStyle(fontSize: 20),
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.baseline,
                    textBaseline: TextBaseline.alphabetic,
                    children: <Widget>[
                      Text(
                        heightVal.toString(),
                        style: kLabelTextStyle,
                      ),
                      Text('cm'),
                    ],
                  ),
                  Slider(
                    min: kminHeight.toDouble(),
                    max: kmaxHeight.toDouble(),
                    value: heightVal.toDouble(),
                    onChanged: (double newValue) {
                      print("New value is $newValue");
                      setState(() {
                        heightVal = newValue.toInt();
                      });
                    },
                  )
                ],
              ),
            ),
          ),
          Expanded(
            child: Row(
              children: <Widget>[
                Expanded(
                  child: ReusableCard(
                    colour: kactiveCardColor,
                    cardChild: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        Text(
                          'WEIGHT',
                          style: labelTextStyle,
                        ),
                        Text(
                          weightVal.toString(),
                          style: kLabelTextStyle,
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          children: <Widget>[
                            RoundIconButton(
                              icon: FontAwesomeIcons.minus,
                              onPressed: () {
                                print("Pressed minus");
                                setState(() {
                                  weightVal--;
                                });
                              },
                            ),
                            RoundIconButton(
                              icon: FontAwesomeIcons.plus,
                              onPressed: () {
                                print("Pressed plus");
                                setState(() {
                                  weightVal++;
                                });
                              },
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
                Expanded(
                  child: ReusableCard(
                    colour: kactiveCardColor,
                    cardChild: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: <Widget>[
                        Text(
                          'AGE',
                          style: labelTextStyle,
                        ),
                        Text(
                          ageVal.toString(),
                          style: kLabelTextStyle,
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          children: <Widget>[
                            RoundIconButton(
                              icon: FontAwesomeIcons.minus,
                              onPressed: () {
                                print("Pressed minus");
                                setState(() {
                                  ageVal--;
                                });
                              },
                            ),
                            RoundIconButton(
                              icon: FontAwesomeIcons.plus,
                              onPressed: () {
                                print("Pressed plus");
                                setState(() {
                                  ageVal++;
                                });
                              },
                            ),
                          ],
                        )
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
          BottomButton(
              label: 'CALCULATE',
              onTap: () {
                BMICalculator bmicalc = BMICalculator(
                    height: heightVal.toDouble(), weight: weightVal.toDouble());
                String bmi = bmicalc.CalcBMI();
                String interpretation = bmicalc.InterpretBMI();
                print("bmi:$bmi inter:$interpretation");

                Navigator.of(context).pushNamed('/results',
                    arguments: {bmi: bmi, interpretation: interpretation});

//                Navigator.pushNamed(context, '/results',
//                    arguments: {bmi: bmi, interpretation: interpretation});
              }),
        ],
      ),
    );
  }
}

计算器_brain.dart:

import 'package:flutter/cupertino.dart';
import 'dart:math';

class BMICalculator {
  double height;
  double weight;
  double _bmi;

  BMICalculator({@required this.height, @required this.weight});

  String CalcBMI() {
    _bmi = weight / pow(height / 100, 2);
    return _bmi.toStringAsFixed(1);
  }

  String InterpretBMI() {
    String interpretation;
    if (_bmi < 18.5) {
      interpretation = "You are underweight";
    } else if (_bmi < 25) {
      interpretation = "You are normal. Excellent.";
    } else if (_bmi < 30) {
      interpretation = "You are overweight.";
    } else if (_bmi < 40) {
      interpretation = "You are obese. You have to exercise more.";
    } else {
      interpretation = "You have severe obesity";
    }
    return interpretation;
  }
}

结果页面:

class ResultsPage extends StatelessWidget {
  ResultsPage({@required this.bmi, @required this.interpretation});

  String bmi;
  String interpretation;
//  print("bmi: $bmi interpretation:$interpretation");

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(
          title: Text('BMI CALCULATOR'),
        ),
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            Expanded(
              child: Container(
                child: Text(
                  "Your Result",
                  style: TextStyle(
                    fontSize: 50,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
            ),
            Expanded(
              flex: 5,
              child: ReusableCard(
                colour: kactiveCardColor,
                cardChild: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    Text(
                      "NORMAL",
                      style: TextStyle(color: Colors.teal[300], fontSize: 25),
                    ),
                    Text(
                      bmi,
                      style:
                          TextStyle(fontSize: 100, fontWeight: FontWeight.bold),
                    ),
                    Text(
                      'Normal BMI Range:',
                      style: TextStyle(
                        color: Colors.grey,
                        fontSize: 20,
                      ),
                    ),
                    Text(
                      "18.5 - 25 kg/m2",
                      style: TextStyle(
                        fontSize: 25,
                      ),
                    ),
                    Center(
                      child: Text(
                        interpretation,
                        style: TextStyle(
                          fontSize: 20,
                        ),
                        textAlign: TextAlign.center,
                      ),
                    ),
                    Container(
                      color: Colors.black45,
                      padding: EdgeInsets.all(20),
                      child: Text("Save Result"),
                    )
                  ],
                ),
//                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              ),
            ),
            BottomButton(
              onTap: () {
                Navigator.pop(context);
              },
              label: 'RE-CALCULATE',
            ),
          ],
        ),
//      appBar: ,
      ),
    );
  }
}

标签: flutterdart

解决方案


在命名路由中,您可以使用在 Navigator.pushNamed() 中定义的 arguments 属性传递数据。

例子:

Navigator.pushNamed(
  context, 
  '/route', 
  arguments: ScreenArguments(
    'Argument 1',
    'Argument 2'
  )
)

另一方面,为了提取参数,您可以使用以下代码:

final ScreenArguments args = ModalRoute.of(context).settings.arguments;

推荐阅读