使用来自另一个类的实例访问有状态小部件的变量时,在 null 上调用 getter 长度
Posted
技术标签:
【中文标题】使用来自另一个类的实例访问有状态小部件的变量时,在 null 上调用 getter 长度【英文标题】:getter length called on null when accessing a variable of a stateful widget using its instance from another class 【发布时间】: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 类
【问题讨论】:
【参考方案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 上调用 getter 长度的主要内容,如果未能解决你的问题,请参考以下文章
使 API 在所有小部件中都可访问 - 使用已实例化变量的 Provider?