Как мне сбросить настройки контроллера, когда я вернусь или закончу?

У меня класс QuestionController расширяется GetxController

Когда я выхожу со страницы с помощью элементов управления, я хочу, чтобы она перестала работать (потому что она все еще работает в фоновом режиме) и запустилась снова, если я вернусь на эту страницу.

Я пробовал: я добавил их после маршрута ScoreScreen()nextQuestion ()):

      _isAnswered = false;
_questionNumber.value = 1; 

Я сбрасываю значения перед тем, как перейти на страницу результатов. Это может сработать, если вы перейдете на страницу результатов, но если вы вернетесь раньше, этого не произойдет. (верхний вопрос № / 4 здесь не работает). Так что этот способ не подходит.

Как я могу остановить и сбросить его, когда страница закрывается?

Код класса контроллера:

      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(),
            ],
          ),
        ],
      ),
    );
  }
}

7 ответов

Решение

Обновленный ответ:

Хорошо, после просмотра вашего полного кода для моего решения требуется пара дополнительных шагов.

Добавьте это в свой класс контроллера. Его нужно вызвать в onPressed из вашего

       void resetQuestionNumber() => _questionNumber.value = 1;

Вам нужно будет инициализировать контроллер раньше, чтобы вы могли добавить его в свой

      final _questionController = Get.put(QuestionController());

В onTap вашей HomeScreen теперь выглядит так.

      onTap: () {
    _questionController.resetQuestionNumber();
    Navigator.push(
    context, MaterialPageRoute(builder: (context) => QuizPage()));
},

Это должно сработать. Индекс не обновлялся до тех пор, пока вам не ответили на вопрос, поэтому просто нужно сбросить _questionNumber перед поездкой в QuizPageи после этого догоняет. Ваш updateTheQuestionNum может уйти полностью, и вам не нужно ничего обрабатывать в onPageChanged из PageView.builder больше.

Оригинальный ответ:

Если ты просто хочешь этого RxInt _questionNumber чтобы соответствовать значению _pageController вы можете добавить слушателя в свой onInit

      _pageController.addListener(() {
  _questionNumber.value = _pageController.page.round() + 1;
});

Изменить: добавлен + 1 для учета индекса, начиная с 0

Если вы хотите сбросить только один контроллер, вы можете использовать Get.delete<ExecutableController>();

для сброса всех контроллеров Get.deleteAll();

вы можете прослушать "onBack event" и избавиться от контроллера, вот пример

      @override
Widget build(BuildContext context) {
  return WillPopScope(
    onWillPop: () {
      disposeController(context);
    },
    child: Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        leading: IconButton(
            icon: Icon(Icons.arrow_back),
            onPressed: () {
              _moveToSignInScreen(context);
            }),
        title: Text("Profile"),
      ),
    ),
  );

}

      void disposeController(BuildContext context){
//or what you wnat to dispose/clear
 _pageController.dispose()
}
      InkWell(
onTap: () {
    /*add QuestionController().refresh();*/
    QuestionController().refresh();
    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),
    ),
),

),

Автоматически:

       Get.to(() => DashboardPage(), binding: BindingsBuilder.put(() => DashboardController()));

Вручную:

Вы можете удалить контроллер на задней кнопке, а затем снова установить его, это даст тот же результат, что и сброс контроллера:

  1. удалите это:

    Получить.удалить();

  2. Добавьте еще раз:

    Get.put(Панель управления());

Вы можете использовать Get.reset(), если у вас только один контроллер, он очищает все зарегистрированные экземпляры.

Используйте initState для решения этой проблемы

В initState вызовите setState, а затем измените значение контроллера на 0 ....

Удачи 😇😇😇...

Другие вопросы по тегам