flutter - 当我回来或完成时如何重置我的 Controller ?

标签 flutter dart flutter-getx

enter image description here

我有一个 QuestionController 类扩展 GetxController

当我使用控件退出页面时,我希望它停止工作(因为它仍在后台运行)并在我返回该页面时重新启动。

我已经尝试过:我在 ScoreScreen() 的路由之后添加了这些(在 nextQuestion () 中):

_isAnswered = false;
_questionNumber.value = 1; 

我在进入评分页面之前重置了数值。如果你去评分页面可能有用,但如果你早点回来,它就不会了。 (上面的问题 num/4 在这里不起作用)。所以这种方式不适合。

有什么方法可以在页面退出时停止并重置它?

Controller 类代码:

class QuestionController extends GetxController
    with SingleGetTickerProviderMixin {
  PageController _pageController;

  PageController get pageController => this._pageController;

  List<Question> _questions = questions_data
      .map(
        (e) => Question(
            id: e["id"],
            question: e["question"],
            options: e["options"],
            answer: e["answer_index"]),
      )
      .toList();

  List<Question> get questions => this._questions;

  bool _isAnswered = false;

  bool get isAnswered => this._isAnswered;

  int _correctAns;

  int get correctAns => this._correctAns;

  int _selectedAns;

  int get selectedAns => this._selectedAns;

  RxInt _questionNumber = 1.obs;

  RxInt get questionNumber => this._questionNumber;

  int _numOfCorrectAns = 0;

  int get numOfCorrectAns => this._numOfCorrectAns;

  @override
  void onInit() {
    _pageController = PageController();
    super.onInit();
  }

  @override
  void onClose() {
    super.onClose();
    _pageController.dispose();
  }

  void checkAns(Question question, int selectedIndex) {
    _isAnswered = true;
    _correctAns = question.answer;
    _selectedAns = selectedIndex;

    if (_correctAns == _selectedAns) _numOfCorrectAns++;

    update();

    Future.delayed(Duration(seconds: 2), () {
      nextQuestion();
    });
  }

  void nextQuestion() {
    if (_questionNumber.value != _questions.length) {
      _isAnswered = false;
      _pageController.nextPage(
          duration: Duration(milliseconds: 300), curve: Curves.ease);
    } else {
      Get.off(ScoreScreen(correctNum: _numOfCorrectAns)); // GetMaterialApp()

      // _isAnswered = false;

      _numOfCorrectAns = 0;

      //_questionNumber.value = 1;

    }
  }

  void updateTheQuestionNum(int index) {
    _questionNumber.value = index + 1;
  }
}

完整代码如下

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:get/get.dart';  // get: ^3.25.4

//  QuizPage()     ===============> 50. line      (Question 1/4) 81. line
//  QuestionCard()  ==============> 116. line
//  Option()   ===================> 163. line
//  QuestionController()  ========> 218. line
//  ScoreScreen() ================> 345. line

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(canvasColor: Colors.blue),
      home: HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home Page"),
      ),
      body: Center(
        child: InkWell(
          onTap: () {
            Navigator.push(
                context, MaterialPageRoute(builder: (context) => QuizPage()));
          },
          child: Container(
            padding: EdgeInsets.all(22),
            color: Colors.green,
            child: Text(
              "Go Quiz Page",
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ),
    );
  }
}

class QuizPage extends StatelessWidget {
  const QuizPage({
    Key key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    QuestionController _questionController = Get.put(QuestionController());

    return Scaffold(
      appBar: AppBar(
        title: Text("Quiz Page"),
      ),
      body: Stack(
        children: [
          SafeArea(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                SizedBox(
                  height: 16,
                ),
                Padding(
                  padding: EdgeInsets.symmetric(horizontal: 16),
                  child: Obx(
                    () => Center(
                      child: RichText(
                          text: TextSpan(
                              // text,style default adjust here OR:children[TextSpan(1,adjust 1),TextSpan(2,adjust 2),..]
                              text:
                                  "Question ${_questionController._questionNumber.value}",
                              style: TextStyle(
                                  fontSize: 33, color: Colors.white70),
                              children: [
                            TextSpan(
                                text:
                                    "/${_questionController._questions.length}",
                                style: TextStyle(fontSize: 25))
                          ])),
                    ),
                  ),
                ),
                Divider(color: Colors.white70, thickness: 1),
                SizedBox(
                  height: 16,
                ),
                Expanded(
                  child: PageView.builder(
                    physics: NeverScrollableScrollPhysics(),
                    controller: _questionController._pageController,
                    onPageChanged: _questionController.updateTheQuestionNum,
                    itemCount: _questionController.questions.length,
                    itemBuilder: (context, index) => QuestionCard(
                      question: _questionController.questions[index],
                    ),
                  ),
                )
              ],
            ),
          )
        ],
      ),
    );
  }
}

class QuestionCard extends StatelessWidget {
  final Question question;

  const QuestionCard({
    Key key,
    @required this.question,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    QuestionController _controller = Get.put(QuestionController());

    return Container(
      margin: EdgeInsets.only(left: 16, right: 16, bottom: 16),
      padding: EdgeInsets.all(16),
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(25),
        color: Colors.white,
      ),
      child: Column(
        children: [
          Text(
            question.question,
            style: TextStyle(fontSize: 22),
          ),
          SizedBox(
            height: 8,
          ),
          Flexible(
            child: SingleChildScrollView(
              child: Column(
                children: [
                  ...List.generate(
                      question.options.length,
                      (index) => Option(
                          text: question.options[index],
                          index: index,
                          press: () => _controller.checkAns(question, index)))
                ],
              ),
            ),
          )
        ],
      ),
    );
  }
}

class Option extends StatelessWidget {
  final String text;
  final int index;
  final VoidCallback press;

  const Option({
    Key key,
    @required this.text,
    @required this.index,
    @required this.press,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GetBuilder<QuestionController>(
        init: QuestionController(),
        builder: (q) {
          Color getRightColor() {
            if (q.isAnswered) {
              if (index == q._correctAns) {
                return Colors.green;
              } else if (index == q.selectedAns &&
                  q.selectedAns != q.correctAns) {
                return Colors.red;
              }
            }
            return Colors.blue;
          }

          return InkWell(
            onTap: press,
            child: Container(
              //-- Option
              margin: EdgeInsets.only(top: 16),
              padding: EdgeInsets.all(16),
              decoration: BoxDecoration(
                  color: getRightColor(),
                  borderRadius: BorderRadius.circular(16)),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(
                    "${index + 1}. $text",
                    style: TextStyle(fontSize: 16, color: Colors.white),
                  ),
                ],
              ),
            ),
          );
        });
  }
}

class QuestionController extends GetxController
    with SingleGetTickerProviderMixin {
  PageController _pageController;

  PageController get pageController => this._pageController;

  List<Question> _questions = questions_data
      .map(
        (e) => Question(
            id: e["id"],
            question: e["question"],
            options: e["options"],
            answer: e["answer_index"]),
      )
      .toList();

  List<Question> get questions => this._questions;

  bool _isAnswered = false;

  bool get isAnswered => this._isAnswered;

  int _correctAns;

  int get correctAns => this._correctAns;

  int _selectedAns;

  int get selectedAns => this._selectedAns;

  RxInt _questionNumber = 1.obs;

  RxInt get questionNumber => this._questionNumber;

  int _numOfCorrectAns = 0;

  int get numOfCorrectAns => this._numOfCorrectAns;

  @override
  void onInit() {
    _pageController = PageController();
    //_pageController.addListener(() { _questionNumber.value = _pageController.page.round()+1; });
    super.onInit();
  }

  @override
  void onClose() {
    super.onClose();
    _pageController.dispose();
  }

  void checkAns(Question question, int selectedIndex) {
    _isAnswered = true;
    _correctAns = question.answer;
    _selectedAns = selectedIndex;

    if (_correctAns == _selectedAns) _numOfCorrectAns++;

    update();

    Future.delayed(Duration(seconds: 2), () {
      nextQuestion();
    });
  }

  void nextQuestion() {
    if (_questionNumber.value != _questions.length) {
      _isAnswered = false;
      _pageController.nextPage(
          duration: Duration(milliseconds: 300), curve: Curves.ease);
    } else {
      Get.off(ScoreScreen(correctNum: _numOfCorrectAns)); // GetMaterialApp()

      // _isAnswered = false;

      _numOfCorrectAns = 0;

      //_questionNumber.value = 1;

    }
  }

  void updateTheQuestionNum(int index) {
    _questionNumber.value = index + 1;
  }
}

class Question {
  final int id, answer;
  final String question;
  final List<String> options;

  Question({
    @required this.id,
    @required this.question,
    @required this.options,
    @required this.answer,
  });
}

const List questions_data = [
  {
    "id": 1,
    "question": "Question 1",
    "options": ['option A', 'B', 'C', 'D'],
    "answer_index": 3,
  },
  {
    "id": 2,
    "question": "Question 2",
    "options": ['option A', 'B', 'C', 'D'],
    "answer_index": 2,
  },
  {
    "id": 3,
    "question": "Question 3",
    "options": ['option A', 'B', 'C', 'D'],
    "answer_index": 0,
  },
  {
    "id": 4,
    "question": "Question 4",
    "options": ['option A', 'B', 'C', 'D'],
    "answer_index": 0,
  },
];

class ScoreScreen extends StatelessWidget {
  final int correctNum;

  ScoreScreen({@required this.correctNum});

  @override
  Widget build(BuildContext context) {
    QuestionController _qController = Get.put(QuestionController());

    return Scaffold(
      body: Stack(
        fit: StackFit.expand,
        children: [
          Column(
            children: [
              Spacer(
                flex: 2,
              ),
              Text(
                "Score",
                style: TextStyle(fontSize: 55, color: Colors.white),
              ),
              Spacer(),
              Text(
                "${correctNum * 10}/${_qController.questions.length * 10}",
                style: TextStyle(fontSize: 33, color: Colors.white),
              ),
              Spacer(
                flex: 2,
              ),
              InkWell(
                onTap: () => Get.back(),
                borderRadius: BorderRadius.circular(16),
                child: Container(
                  padding: EdgeInsets.all(16),
                  decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(16),
                      color: Colors.white24),
                  child: Text(
                    "Back to Home Page",
                    style: TextStyle(color: Colors.white),
                  ),
                ),
              ),
              Spacer(),
            ],
          ),
        ],
      ),
    );
  }
}

最佳答案

如果你只想重置一个 Controller 那么你可以使用Get.delete<ExecutableController>();

用于重置所有 Controller Get.deleteAll();

关于flutter - 当我回来或完成时如何重置我的 Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66292416/

相关文章:

flutter - Flutter&AlertDialog:加载后我的应用程序不显示警报对话框

android - Flutter 中的控制台消息

flutter - 如何让键盘超出我的内容?

flutter - 在静态方法中传递 BuildContext 会导致 Flutter 中的内存泄漏吗?

variables - Dart-如何将迭代器值传递到Dart中的回调中?

flutter - AnimatedSwitcher不在小部件之间切换

dart - 如何在 Flutter 小部件上模拟点击事件?

flutter - Getx Flutter - 更新列表中的项目不是 react 性的

flutter Getx : Can obs create a global variable?

flutter - 当此属性更改时,如何对显示对象属性的文本小部件进行 react 性更新?这与 GetX