skip to Main Content

`my problem is when i pop this screen then come back , i can’t access to ref.read and and exception Bad state: Cannot use "ref" after the widget was disposed

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:learn_with_lina/providers/messages_provider.dart';

class _CallScreenState extends ConsumerState<CallScreen> {

void initState() {
  print("start call Screen");
  super.initState();
  initSpeechToText();
}

  MessageModel addMessageToList(
    {required String text, required bool received, required bool isLoading}) {
   final messageModel =
     MessageModel(text: text, received: received, isLoading: isLoading);

   ref.read(messagesProvider.notifier).addMessage(messageModel);

   return messageModel;
  }

  void updateMessageInList(
   {required MessageModel messageModel,
   required String text,
   required bool isLoading,
   required bool error}) {
  ref
     .read(messagesProvider.notifier)
    .updateMessage(messageModel, text, isLoading, error);
  }

  void sendMessage(String text) async {
   if (!mounted) return;
    // add the message of user to the list of messages
   addMessageToList(text: text, received: false, isLoading: false);
   setState(() {
   isLoadingSendMessage = true;
  });

  // get old messages
   final oldMessages = ref.read(messagesProvider);
  // add Loader to the List view
  final assistantMessage = addMessageToList(
    text: '', received: true, isLoading: isLoadingSendMessage);
   // call chat gpt
   final answer = await ChatGptApi.getChatGptAnswer(text, oldMessages);
   setState(() {
   isLoadingSendMessage = false;
   });
   if (answer.trim().isNotEmpty) {
    bool error = false;
    if (answer.trim() == 'An internal error occurred') {
     error = true;
   }
    updateMessageInList(
      messageModel: assistantMessage,
      text: answer.trim(),
      isLoading: isLoadingSendMessage,
      error: error);
    systemSpeak(answer);
  }
 }

i tried to check if(!mounted) but in this cas the mounted value is always false after comme back to this screen

2

Answers


  1. i tried to check if(!mounted) but in this cas the mounted value is
    always false after comme back to this screen

    That makes sense, you popped the route and come back pushing it again, so the previous one is not mounted anymore. This seems more a problem of understanding the lifecycle of the widgets and widget tree more than Riverpod but if you really insist of using that callback method after being disposed you could just save a reference to your provider as a variable and use it:

    class _CallScreenState extends ConsumerState<CallScreen> {
    late MessageProvider messageP; ///<---- use this reference in your methods
    
    void initState() {
      print("start call Screen");
      super.initState();
      initSpeechToText();
      messageP = ref.read(messagesProvider.notifier);
    }
    
      MessageModel addMessageToList(
        {required String text, required bool received, required bool isLoading}) {...
      }
    
      void updateMessageInList(
       {required MessageModel messageModel,
       required String text,
       required bool isLoading,
       required bool error}) {...
      }
    
      void sendMessage(String text) async {...
     }
    
     @override
     void dispose() {
         messageP = ref.read(messagesProvider.notifier);
     }
    

    Still take this with cautios, and try to cahnge your logic inside your provider (which seems more logical) so you can send messages even when your widget is disposed

    Login or Signup to reply.
  2. If you have a call to ref inside initSpeechToText, then you can’t call it directly in the initState. You have to put it inside this callback:

    void initState() {
      // ...
    
      WidgetsBinding.instance.addPostFrameCallback((_) {
        initSpeechToText();
      });
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search