Calling Get.back() inside a Obx() listener in a flutter app

Viewed 235

I am trying to pop from the current screen when a certain condition from a GetXController is true.

What I did was that I called if (!_isReceiverIDLoggedIn) Get.back(); inside the Obx listener.

This gave me the final outcome I wanted but I am getting an exception.

I would appreciate if someone can suggest a fix handle this issue/exception?

════════ Exception caught by animation library ═════════════════════════════════
The following assertion was thrown while notifying status listeners for AnimationController:
setState() or markNeedsBuild() called during build.

This Overlay widget cannot be marked as needing to build because the framework is already in the process of building widgets.  A widget can be marked as needing to be built during the build phase only if one of its ancestors is currently building. This exception is allowed because the framework builds parent widgets before children, which means a dirty descendant will always be built. Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was: Overlay-[LabeledGlobalKey<OverlayState>#5221d]
    state: OverlayState#794f1(tickers: tracking 0 tickers, entries: [OverlayEntry#26cd8(opaque: true; maintainState: false), OverlayEntry#d189a(opaque: false; maintainState: true), OverlayEntry#0dfc3(opaque: false; maintainState: false), OverlayEntry#0636b(opaque: false; maintainState: true)])
The widget which was currently being built when the offending call was made was: Obx
    dirty
    state: _ObxState#5b9ea
When the exception was thrown, this was the stack
#0      Element.markNeedsBuild.<anonymous closure>
package:flutter/…/widgets/framework.dart:4217
#1      Element.markNeedsBuild
package:flutter/…/widgets/framework.dart:4232
#2      State.setState
package:flutter/…/widgets/framework.dart:1108
#3      OverlayState._didChangeEntryOpacity
package:flutter/…/widgets/overlay.dart:475
#4      OverlayEntry.opaque=
package:flutter/…/widgets/overlay.dart:92
...
The AnimationController notifying status listeners was: AnimationController#4d86f(◀ 1.000; for MaterialPageRoute<dynamic>(/message))
════════════════════════════════════════════════════════════════════════════════

Here is the full flutter code:

import 'package:flutter/material.dart';
import 'package:flutter_frontend/controller/user/user_controller.dart';
import 'package:get/get.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

import 'package:flutter_frontend/controller/message/message_controller.dart';
import 'package:flutter_frontend/view/message/components/message_unit.dart';

class MessageView extends StatefulWidget {
  final String receiverID;

  MessageView({required this.receiverID});

  @override
  _MessageViewState createState() => _MessageViewState();
}

class _MessageViewState extends State<MessageView> {
  final ItemScrollController itemScrollController = ItemScrollController();
  final ItemPositionsListener itemPositionsListener =
      ItemPositionsListener.create();
  final MessageController _messageController = Get.find();
  final UserController _userController = Get.find();

  bool _isWidgetTreeBuilt = false;

  @override
  void initState() {
    super.initState();
    _startUpSequence();
  }

  _startUpSequence() async {
    _isWidgetTreeBuilt = false;
    //if the messages are loading - is the messages fetched from the db is not empty
    //then using a WidgetsBinding.instance?.addPostFrameCallback a  itemScrollController.jumpTo is excuted
    //the WidgetsBinding.instance?.addPostFrameCallback ensures that the jumpTo happens after the Widget tree is mounted
    if (_messageController.getMessageStatus.value == MessageStatus.loaded) {
      WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
        itemScrollController.jumpTo(
            index: _messageController.getMessageList.length - 1);
      });
    }
    WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
      _isWidgetTreeBuilt = true;
    });
  }

  @override
  Widget build(BuildContext context) {
      return Obx(() {
        //if the receiverID is disconnected from the socket, the MessageScreen is popped 
        bool _isReceiverIDLoggedIn = _userController.getUsersList
          .any((user) => user.id == widget.receiverID);

      if (!_isReceiverIDLoggedIn) Get.back();

       /*if the MessageStatus in the MessageController is not empty 
       and if the widget tree is built and if the MessageList length is more than 9
      the itemScrollController is activated to scroll the latest  MessageUnit 
      from outside the viewinset to bottom of viewinset
       */

      if (_messageController.getMessageStatus.value != MessageStatus.empty &&
          _isWidgetTreeBuilt &&
          _messageController.getMessageList.length > 9) {
        itemScrollController.scrollTo(
            index: _messageController.getMessageList.length - 1,
            duration: Duration(milliseconds: 500),
            curve: Curves.easeInOutCubic,
            alignment: 0.725);
      }

      switch (_messageController.getMessageStatus.value) {
        case MessageStatus.loading:
          return Flexible(
            child: Center(
              child: CircularProgressIndicator(),
            ),
          );
        case MessageStatus.loaded:
          return Flexible(
            child: ScrollablePositionedList.builder(
              itemScrollController: itemScrollController,
              itemPositionsListener: itemPositionsListener,
              itemCount: _messageController.getMessageList.length,
              itemBuilder: (context, index) {
                return MessageUnit(
                    message: _messageController.getMessageList[index]);
              },
            ),
          );
        case MessageStatus.empty:
          return Flexible(
            child: Center(
              child: Text(
                'No Messages Found!',
                style: Theme.of(context).textTheme.subtitle1,
              ),
            ),
          );
        default:
          return Container();
      }
    });
  }
}
0 Answers
Related