我正在嘗試使用顫振制作一個簡單的測驗應用程式,但這已經困擾了我一天多
該錯誤主要表明在構建 Quiz 期間呼叫了 myApp。即使我也在 youtube 上搜索過,我也不知道該怎么辦。
錯誤資訊

Main.dart 代碼:
import 'package:first/result.dart';
import 'package:flutter/material.dart';
import './quiz.dart';
import './result.dart';
void main(List<String> args) => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
final _questions = [
{
'questionText': 'What\'s your favorite colour?',
'answers': ['Black', 'Red', 'Blue', 'Green'],
},
{
'questionText': 'What\'s your favorite animal?',
'answers': ['Cat', 'Dog', 'Pig', 'Parrot'],
},
{
'questionText': 'Who\'s your favorite wrestler?',
'answers': ['Seth Rollins', 'Roman Reigns', 'John Cena', 'Randy Orton'],
},
];
var _questionIndex = 0;
void _answerQuestion() {
setState(() {});
_questionIndex = _questionIndex 1;
print(_questionIndex);
if (_questionIndex < _questions.length) {
print('We have more Questions for you !!');
} else {
print('No more questions left !!');
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body: _questionIndex < _questions.length
? Quiz(
answerQuestion: _answerQuestion,
questionIndex: _questionIndex,
questions: _questions)
: Result(),
),
);
}
}
quiz.dart 代碼:
import './question.dart';
import './answer.dart';
class Quiz extends StatelessWidget {
final List<Map<String, Object>> questions;
final int questionIndex;
final Function answerQuestion;
Quiz({required this.questions, required this.answerQuestion, required this.questionIndex});
@override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map((answer) {
return Answer(answerQuestion(), answer);
}).toList()
],
);
}
}
result.dart 代碼:
import 'package:flutter/material.dart';
class Result extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text('All questions are answered !!'),
);
}
}
answer.dart 代碼:
import 'package:flutter/material.dart';
class Answer extends StatelessWidget {
final VoidCallback selectHandler;
final String answerText;
Answer(this.selectHandler, this.answerText);
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: RaisedButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: selectHandler,
child: Text(answerText)),
);
}
}
question.dart 代碼:
import 'package:flutter/material.dart';
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10.0),
child: Text(questionText,
style: TextStyle(fontSize: 28), textAlign: TextAlign.center),
);
}
}
請幫忙。
uj5u.com熱心網友回復:
您收到錯誤訊息的原因是每次呼叫 MyApp 小部件的 build 方法時您都在呼叫 setState。setState 方法將重新觸發小部件的構建,然后再次呼叫 setState。所以基本上你有一個無限的重新渲染。
如果您查看您的代碼,quiz.dart我們會發現這種無限重新渲染的原因:
@override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map((answer) {
return Answer(answerQuestion() /*<-- here is the problem*/, answer);
}).toList()
],
);
}
每次測驗小部件呼叫它的 build 方法時,它都會呼叫 answerQuestion 方法,該方法將呼叫您的主小部件的 build 方法,進而重新構建測驗小部件。而不是在這里呼叫該方法,您應該將此回呼方法進一步向下發送三個到答案小部件:
class Quiz extends StatelessWidget {
final List<Map<String, Object>> questions;
final int questionIndex;
final Function answerQuestion;
Quiz({required this.questions, required this.answerQuestion, required this.questionIndex});
@override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map((answer) {
return Answer(answerQuestion /* Notice the difference */, answer);
}).toList()
],
);
}
}
class Answer extends StatelessWidget {
final Function answerQuestion; // I renamed this to answerQuestion, feel free to stick with selectHandler
final String answerText;
Answer(this.answerQuestion, this.answerText);
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: RaisedButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: answerQuestion,
child: Text(answerText)),
);
}
}
我還建議您更新 answerQuestion 方法小部件中的邏輯,因此您將 setState 方法包裝在您正在執行的狀態更新周圍:
void _answerQuestion() {
setState(() {
_questionIndex = _questionIndex 1;
});
print(_questionIndex);
if (_questionIndex < _questions.length) {
print('We have more Questions for you !!');
} else {
print('No more questions left !!');
}
}
uj5u.com熱心網友回復:
根據您提供的代碼,您似乎只是將代碼中的函式實體傳遞_answerQuestion給main.dart其他檔案。根據我使用 dart 和 Flutter 的經驗,強烈建議將函式傳遞給小部件時,應始終以以下方式傳遞它:
Quiz(
answerQuestion: () => _answerQuestion(), // pass it like this to avoid errors.
questionIndex: _questionIndex,
questions: _questions)
也就是說,您應該將其作為 lambda/匿名函式傳遞。IE
void yourFunction() {
// You do something here
}
AnyWidget(
onPressed: () => yourFunction();, // This is called a lambda/anonymous function.
);
這樣做的原因是,onPressed: yourFunction,即使用戶實際上沒有與應用程式互動,像這樣傳遞的函式也會被呼叫,即在構建小部件時它會被呼叫。為了避免這種情況,我們使用 lambda 函式。
如果我的回答有幫助,請將我的回答標記為正確。謝謝!
uj5u.com熱心網友回復:
主要問題發生在使用函式時Answer和小部件上。Quiz
使用VoidCallbackonQuiz而不是Funtion.
class Quiz extends StatelessWidget {
final List<Map<String, Object>> questions;
final int questionIndex;
final VoidCallback answerQuestion;
const Quiz({
Key? key,
required this.questions,
required this.answerQuestion,
required this.questionIndex,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map(
(answer) {
return Answer(answerQuestion, answer);
},
).toList()
],
);
}
}
完整片段
import 'package:flutter/material.dart';
void main(List<String> args) => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
final _questions = [
{
'questionText': 'What\'s your favorite colour?',
'answers': ['Black', 'Red', 'Blue', 'Green'],
},
{
'questionText': 'What\'s your favorite animal?',
'answers': ['Cat', 'Dog', 'Pig', 'Parrot'],
},
{
'questionText': 'Who\'s your favorite wrestler?',
'answers': ['Seth Rollins', 'Roman Reigns', 'John Cena', 'Randy Orton'],
},
];
var _questionIndex = 0;
void _answerQuestion() {
setState(() {});
_questionIndex = _questionIndex 1;
print(_questionIndex);
if (_questionIndex < _questions.length) {
print('We have more Questions for you !!');
} else {
print('No more questions left !!');
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('My First App'),
),
body: _questionIndex < _questions.length
? Quiz(
answerQuestion: _answerQuestion,
questionIndex: _questionIndex,
questions: _questions)
: Result(),
),
);
}
}
class Quiz extends StatelessWidget {
final List<Map<String, Object>> questions;
final int questionIndex;
final VoidCallback answerQuestion;
const Quiz({
Key? key,
required this.questions,
required this.answerQuestion,
required this.questionIndex,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
children: [
Question(questions[questionIndex]['questionText'] as String),
...(questions[questionIndex]['answers'] as List<String>).map(
(answer) {
return Answer(answerQuestion, answer);
},
).toList()
],
);
}
}
class Answer extends StatelessWidget {
final VoidCallback selectHandler;
final String answerText;
Answer(this.selectHandler, this.answerText);
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: RaisedButton(
color: Colors.blue,
textColor: Colors.white,
onPressed: selectHandler,
child: Text(answerText),
),
);
}
}
class Question extends StatelessWidget {
final String questionText;
Question(this.questionText);
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: EdgeInsets.all(10.0),
child: Text(questionText,
style: TextStyle(fontSize: 28), textAlign: TextAlign.center),
);
}
}
class Result extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text('All questions are answered !!'),
);
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/495138.html
上一篇:DartFlutter:如何將字串中的字符替換為數字(反之亦然)?
下一篇:Linux yum的實作和配置
