【问题标题】:getter length called on null when accessing a variable of a stateful widget using its instance from another class使用来自另一个类的实例访问有状态小部件的变量时,在 null 上调用 getter 长度
【发布时间】:2020-08-09 16:21:03
【问题描述】:

最初,我使用页面路由将数据发送到下一页(问题)。 (数据为List类型)

Navigator.pushReplacement(context,MaterialPageRoute(
                                        builder: (context) => Question(
                                            questions: this.questions)));

然后我使用构造函数接收到 Question Stateful 类中的值并将其值设置为另一个变量。

问题类:

class Question extends StatefulWidget {
  final List<QuestionModel> questions;

    const Question({this.questions});

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

class _QuestionState extends State<Question> {
  @override
  void initState() {
    super.initState();
    print(widget.questions); //<----------working
  }

  @override
  Widget build(BuildContext context){
  return Scaffold(
    body: Column(
      children: <Widget>[
        Timer(),
        SizedBox(height: 40),
        Expanded(child: QuestionBuilder())
      ],
    ),
  );}

当我尝试在 Question 状态下打印问题列表时,它工作得很好。

但我需要另一个类 QuestionBuilder 中的值。 因此,我使用 Question Class 的实例访问了该值。

 class QuestionBuilder extends StatefulWidget {
      @override
      _QuestionBuilderState createState() => _QuestionBuilderState();
    }

        class _QuestionBuilderState extends State<QuestionBuilder> {
          List<QuestionModel> questions;

          @override
          void initState() {
            super.initState();
            questions = Question().questions;
            print(questions); //<---------------not working
          } 

         @override
       Widget build(BuildContext context) {
    return PageView.builder(
      itemCount: questions.length ?? 0,
      itemBuilder: (context, index) {
        return SingleChildScrollView(
          child: Column(
            children: <Widget>[
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 20),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: <Widget>[
                    Text(
                      "Question  ${index + 1} / ",
                      style: Styles.questionNumberTextStyle,
                    ),
                    Text(
                      "7",
                      style:
                          Styles.questionNumberTextStyle.copyWith(fontSize: 20),
                    ),
                  ],
                ),
              ),
              SizedBox(height: 20),
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 20),
                child: Text(
                  questions[index].question,
                  style: Styles.questionTextStyle,
                  textAlign: TextAlign.left,
                ),
              ),
              SizedBox(height: 20),
              option(option: questions[index].option_1, onTap: () {}),
              option(option: questions[index].option_2, onTap: () {}),
              option(option: questions[index].option_3, onTap: () {}),
              option(option: questions[index].option_4, onTap: () {}),
              SizedBox(height: 20),
            ],
          ),
        );
      },
    );
  }}

现在当我打印问题列表时它为空,当我在 PageView 或 ListView 中使用它时,错误显示在 null 上调用了 getter 长度。

我不知道是什么导致了问题。 此外,当尝试手动将虚拟列表值分配给 Question 类中的问题列表时。 它适用于 QuestionBuilder 类

【问题讨论】:

    标签: flutter flutter-layout flutter-dependencies flutter-animation flutter-test


    【解决方案1】:

    问题是您正在使用以下代码创建 Question 类的新实例:

    questions = Question().questions;
    

    一种简单的方法是在参数中传递值。例如,在问题类中,您调用 QuestionBuilder() 的参数中传递数据,如下所示:

     @override
      Widget build(BuildContext context){
      return Scaffold(
        body: Column(
          children: <Widget>[
            Timer(),
            SizedBox(height: 40),
            Expanded(child: QuestionBuilder(widget.questions),
    )
          ],
        ),
      );}
    

    现在定义一个变量来访问参数中传递的这个值,如下所示:

     class QuestionBuilder extends StatefulWidget {
    final List<QuestionModel> questions;
    QuestionBuilder(this.questions);
          @override
          _QuestionBuilderState createState() => _QuestionBuilderState();
        }
    
    

    现在在 QuestionBuilder 的 initState 中访问 questionList,如下所示:

     @override
              void initState() {
                super.initState();
                questions = widget.questions;
                print(questions); //<---------------this will work now
              } 
    
    

    所以现在你更正的代码将是,对于问题类:

    class Question extends StatefulWidget {
      final List<QuestionModel> questions;
    
        const Question({this.questions});
    
      @override
      _QuestionState createState() => _QuestionState();
    }
    
    class _QuestionState extends State<Question> {
      @override
      void initState() {
        super.initState();
        print(widget.questions); 
      }
    
      @override
      Widget build(BuildContext context){
      return Scaffold(
        body: Column(
          children: <Widget>[
            Timer(),
            SizedBox(height: 40),
            Expanded(child: QuestionBuilder(widget.questions))
          ],
        ),
      );}
    

    而 QuestionBuilder 将是:

    class QuestionBuilder extends StatefulWidget {
    final List<QuestionModel> questions;
    QuestionBuilder(this.questions);
          @override
          _QuestionBuilderState createState() => _QuestionBuilderState();
        }
    
            class _QuestionBuilderState extends State<QuestionBuilder> {
              List<QuestionModel> questions;
    
              @override
              void initState() {
                super.initState();
                questions = widget.questions;
                print(questions); //<---------------not working
              } 
    
             @override
           Widget build(BuildContext context) {
        return PageView.builder(
          itemCount: questions.length ?? 0,
          itemBuilder: (context, index) {
            return SingleChildScrollView(
              child: Column(
                children: <Widget>[
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 20),
                    child: Row(
                      crossAxisAlignment: CrossAxisAlignment.end,
                      children: <Widget>[
                        Text(
                          "Question  ${index + 1} / ",
                          style: Styles.questionNumberTextStyle,
                        ),
                        Text(
                          "7",
                          style:
                              Styles.questionNumberTextStyle.copyWith(fontSize: 20),
                        ),
                      ],
                    ),
                  ),
                  SizedBox(height: 20),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 20),
                    child: Text(
                      questions[index].question,
                      style: Styles.questionTextStyle,
                      textAlign: TextAlign.left,
                    ),
                  ),
                  SizedBox(height: 20),
                  option(option: questions[index].option_1, onTap: () {}),
                  option(option: questions[index].option_2, onTap: () {}),
                  option(option: questions[index].option_3, onTap: () {}),
                  option(option: questions[index].option_4, onTap: () {}),
                  SizedBox(height: 20),
                ],
              ),
            );
          },
        );
      }}
    

    【讨论】:

    • 嘿,感谢您的回复......它就像一个魅力......非常感谢你拯救了我的一天!......顺便说一句为什么 Question().questions 没有不工作
    • @BalaGanesh 发生这种情况有两个原因。首先,您正在创建一个 Question 类的新实例来获取错误的 questions 字段,其他事情它编译成功,因为您已将 questions 字段作为可选参数,所以当您调用 Question().questions 时,您正在创建一个新的将 List 问题传递为 null 的问题类对象
    猜你喜欢
    • 1970-01-01
    • 2020-02-09
    • 2020-07-31
    • 1970-01-01
    • 2020-03-20
    • 2021-07-12
    • 2018-12-04
    • 2012-05-21
    相关资源
    最近更新 更多