skip to Main Content

I started studying mobile development and had a lot of questions and problems. I have classes. I’m passing a field value "score" and getting an error. Help me to understand. Thank you.
My error: type ‘() => Null’ is not a subtype of type ‘(int) => void’ in type cast

this’s main

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

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  static const _questions = [
    {
      'questionText': 'What's your favorite color?',
      'answers': [
        {'text': 'Red', 'score': 10},
        {'text': 'Blue', 'score': 7},
        {'text': 'Green', 'score': 5},
        {'text': 'Yellow', 'score': 2},
      ],
    },
    {
      'questionText': 'What do you do?',
      'answers': [
        {'text': 'Eat', 'score': 9},
        {'text': 'Sleep', 'score': 10},
        {'text': 'Drink water', 'score': 4},
        {'text': 'Run', 'score': 3},
      ],
    },
    {
      'questionText': 'Do you have chairs?',
      'answers': [
        {'text': 'Yes', 'score': 10},
        {'text': 'No', 'score': 1},
        {'text': 'A lot', 'score': 3},
        {'text': 'I don't know', 'score': 7},
      ],
    },
    {
      'questionText': 'Would you like some red wine?',
      'answers': [
        {'text': 'Yes', 'score': 1},
        {'text': 'No', 'score': 9},
        {'text': 'I don't drink alcohol', 'score': 10},
        {'text': 'No, I would like soda', 'score': 7},
      ],
    },
  ];

  var _questionIndex = 0;
  var _totalScore = 0;

  void _answerQuiz(int score) {
    _totalScore += score;
    setState(() {
      _questionIndex++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'QuiZ',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Quiz'),
        ),
        body: _questionIndex < _questions.length
            ? Quiz(
                questions: _questions,
                questionIndex: _questionIndex,
                answerQuestion: _answerQuiz,
              )
            : Result(_totalScore),
      ),
    );
  }
}

this’s class Quiz

class Quiz extends StatelessWidget {
  final List<Map<String, Object>> questions;
  final int questionIndex;
  final void Function(int) answerQuestion;
  // final VoidCallback answerQuestion;

  const Quiz({
    required this.questions,
    required this.questionIndex,
    required this.answerQuestion,
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          Question(questions[questionIndex]['questionText'] as String),
          ...(questions[questionIndex]['answers'] as List<Map<String, Object>>)
              .map((answer) {
            return Answer(
              answer['text'] as String,
                () {
                  answerQuestion(answer['score'] as int);
                } as void Function(int p1),
            );
          }).toList(),
        ],
      ),
    );
  }
}

this’s class Answer

class Answer extends StatelessWidget {
  final String answerText;
  final void Function(int) selectHandler;
  // final VoidCallback selectHandler;

  const Answer(this.answerText, this.selectHandler, {super.key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      style: const ButtonStyle(
        backgroundColor: MaterialStatePropertyAll(Colors.cyan),
        foregroundColor: MaterialStatePropertyAll(Colors.blueAccent),
      ),
      onPressed: () => selectHandler,
      child: Text(answerText),
    );
  }
}

and this class Result

class Result extends StatelessWidget {
  final int resultScore;
  const Result(this.resultScore, {super.key});

  String get resultPhrase {
    var resultText = 'You did it';
    if (resultScore <= 8) {
      resultText = 'You are awesome and innocent';
    } else if (resultScore <= 12) {
      resultText = 'Pretty likeable';
    } else if (resultScore <= 16) {
      resultText = 'You are ... strange?!';
    } else {
      resultText = 'You are so bad!!!';
    }

    return resultText;
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(resultPhrase),
    );
  }
}

I expected to get the value "score"

2

Answers


  1. the problem is ony Answer class

    the onpressed parameter of ElevatedButton dont receive the type of fuction you want to pass.

    fix it by doing this:
    Corrected the onPressed line to onPressed: selectHandler.

    class Answer extends StatelessWidget {
      final String answerText;
      final void Function() selectHandler;
      // final VoidCallback selectHandler;
    
      const Answer(this.answerText, this.selectHandler, {super.key});
    
      @override
      Widget build(BuildContext context) {
        return ElevatedButton(
          style: const ButtonStyle(
            backgroundColor: MaterialStatePropertyAll(Colors.cyan),
            foregroundColor: MaterialStatePropertyAll(Colors.blueAccent),
          ),
          onPressed: selectHandler, //call the function properly
          child: Text(answerText),
        );
      }
    }
    
    Login or Signup to reply.
  2. Looks like the purpose of selectHandler in Answer is to pass the pressed event to the Quiz widget, so you don’t need to make the function type void Function(int) (and you’re not providing any int value from Answer anyway. Instead, you can make it a VoidCallback and change the way it’s being passed to the onPressed parameter:

    class Answer extends StatelessWidget {
      // ...
      final VoidCallback selectHandler; // (1) change the type
    
      // ...
    
      @override
      Widget build(BuildContext context) {
        return ElevatedButton(
          // ...
          onPressed: selectHandler, // (2) pass it as a tear-off
          // ...
        );
      }
    }
    

    In Quiz, there’s no need to cast the function type:

    class Quiz extends StatelessWidget {
      // ...
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Column(
            children: [
              Question(questions[questionIndex]['questionText'] as String),
              ...(questions[questionIndex]['answers'] as List<Map<String, Object>>)
                  .map((answer) {
                return Answer(
                  answer['text'] as String,
                    () {
                      answerQuestion(answer['score'] as int);
                    }, // (1) remove the type cast
                );
              }).toList(),
            ],
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search