未经手的例外:setState()在distose()时拨打:flutter in flutter

发布于 2025-02-10 08:22:06 字数 5861 浏览 1 评论 0原文

我正在尝试使用setState更改变量的值,但是它给了我这个错误,

Unhandled Exception: setState() called after dispose(): _SplashState#27d6e(lifecycle state: defunct, not mounted, ticker inactive)
E/flutter (12289): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (12289): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (12289): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().

因为上述错误我在屏幕上没有收到通知。

initstate函数中,我正在做通知和firebase令牌并将值存储到sharedPreference。我希望将特定值存储在变量中,以便我可以在“通知”上点击其他屏幕上访问更新值。

这是我的代码,

class Splash extends StatefulWidget {
  const Splash({Key? key}) : super(key: key);
  @override
  _SplashState createState() => _SplashState();
}

class _SplashState extends State<Splash> with SingleTickerProviderStateMixin {
  late AnimationController controller;
  late Animation heartbeatAnimation;

@override
  void initState() {
    super.initState();
 controller = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 500));
    heartbeatAnimation =
        Tween<double>(begin: 100.0, end: 250.0).animate(controller);
    controller.forward().whenComplete(() {
      controller.reverse();
    });


    Future.delayed(const Duration(seconds: 3), () async {
      FirebaseMessaging.onMessage.listen((RemoteMessage message) {
        print("onMessage Clicked!");
       
        String getId = message.data["id"];
        print("ride id get:    ${message.data["id"]}");
        if (mounted) {     
          setState(() {
            bookedRideId = int.parse(getId);   //this line is not wwrking, error points here
          });
        }
        RemoteNotification? notification = message.notification;
        AndroidNotification? android = message.notification?.android;
        if (notification != null && android != null) {
          flutterLocalNotificationsPlugin.show(
              notification.hashCode,
              notification.title,
              notification.body,
              NotificationDetails(
                android: AndroidNotificationDetails(
                  channel.id,
                  channel.name,
                  icon: android.smallIcon,
                ),
              ));
        }
      });
    
      getToken();

      FirebaseMessaging.onBackgroundMessage(
          _firebaseMessagingBackgroundHandler);

      // assign channel (required after android 8)
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>()
          ?.createNotificationChannel(channel);

      // initialize notification for android
      var initialzationSettingsAndroid =
          AndroidInitializationSettings('@mipmap/ic_launcher');
      var initializationSettings =
          InitializationSettings(android: initialzationSettingsAndroid);
      flutterLocalNotificationsPlugin.initialize(initializationSettings);

      final NotificationAppLaunchDetails? notificationAppLaunchDetails =
          await flutterLocalNotificationsPlugin
              .getNotificationAppLaunchDetails();

      
      payload = notificationAppLaunchDetails!.payload;
      if (payload != null) {
        routeToGo = '/second';
        navigatorKey.currentState?.pushNamed('/second');
      }

      await flutterLocalNotificationsPlugin.initialize(initializationSettings,
          onSelectNotification: selectNotification);

      FirebaseMessaging.onMessageOpenedApp
          .listen((RemoteMessage message) async {
        print(message.notification!.body != null);
        if (message.notification!.body != null) {
          print("=======================rideid=====================");
          print(rideId);
          navigatorKey.currentState?.pushNamed('/second');
        }
      });

     

      SharedPreferences prefs = await SharedPreferences.getInstance();
      
      emailAddress = prefs.getString('email').toString();
      token = prefs.getString('token').toString();
      emailAddress == "null" && token == "null"
          ? Navigator.of(context).pushAndRemoveUntil(
              MaterialPageRoute(builder: (context) => const PreLogin()),
              (route) => false)
          : role == "driver"
              ? Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (context) => DriverHome()),
                  (route) => false)
              : Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (context) => const UserHome()),
                  (route) => false);
    });

   
  }

  @override
  void dispose() {
    controller.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
          resizeToAvoidBottomInset: false,
          body: Container(
            decoration: const BoxDecoration(
              image: DecorationImage(
                image: AssetImage(splashBgImage),
                fit: BoxFit.fill,
              ),
            ),
            child: const Logo(),
          )),
    );
  }
}

请帮助我解决此问题。

I'm trying to change the value of a variable using setState but it gives me this error

Unhandled Exception: setState() called after dispose(): _SplashState#27d6e(lifecycle state: defunct, not mounted, ticker inactive)
E/flutter (12289): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (12289): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (12289): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().

Because of the above error i'm not getting notification on my screen.

In initState function, i'm doing to get the notifications and firebase token and storing the values to sharedPreference. I want a specific value to be stored in variable so i can access the updated value on other screen on tap on notification.

here is my code

class Splash extends StatefulWidget {
  const Splash({Key? key}) : super(key: key);
  @override
  _SplashState createState() => _SplashState();
}

class _SplashState extends State<Splash> with SingleTickerProviderStateMixin {
  late AnimationController controller;
  late Animation heartbeatAnimation;

@override
  void initState() {
    super.initState();
 controller = AnimationController(
        vsync: this, duration: const Duration(milliseconds: 500));
    heartbeatAnimation =
        Tween<double>(begin: 100.0, end: 250.0).animate(controller);
    controller.forward().whenComplete(() {
      controller.reverse();
    });


    Future.delayed(const Duration(seconds: 3), () async {
      FirebaseMessaging.onMessage.listen((RemoteMessage message) {
        print("onMessage Clicked!");
       
        String getId = message.data["id"];
        print("ride id get:    ${message.data["id"]}");
        if (mounted) {     
          setState(() {
            bookedRideId = int.parse(getId);   //this line is not wwrking, error points here
          });
        }
        RemoteNotification? notification = message.notification;
        AndroidNotification? android = message.notification?.android;
        if (notification != null && android != null) {
          flutterLocalNotificationsPlugin.show(
              notification.hashCode,
              notification.title,
              notification.body,
              NotificationDetails(
                android: AndroidNotificationDetails(
                  channel.id,
                  channel.name,
                  icon: android.smallIcon,
                ),
              ));
        }
      });
    
      getToken();

      FirebaseMessaging.onBackgroundMessage(
          _firebaseMessagingBackgroundHandler);

      // assign channel (required after android 8)
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>()
          ?.createNotificationChannel(channel);

      // initialize notification for android
      var initialzationSettingsAndroid =
          AndroidInitializationSettings('@mipmap/ic_launcher');
      var initializationSettings =
          InitializationSettings(android: initialzationSettingsAndroid);
      flutterLocalNotificationsPlugin.initialize(initializationSettings);

      final NotificationAppLaunchDetails? notificationAppLaunchDetails =
          await flutterLocalNotificationsPlugin
              .getNotificationAppLaunchDetails();

      
      payload = notificationAppLaunchDetails!.payload;
      if (payload != null) {
        routeToGo = '/second';
        navigatorKey.currentState?.pushNamed('/second');
      }

      await flutterLocalNotificationsPlugin.initialize(initializationSettings,
          onSelectNotification: selectNotification);

      FirebaseMessaging.onMessageOpenedApp
          .listen((RemoteMessage message) async {
        print(message.notification!.body != null);
        if (message.notification!.body != null) {
          print("=======================rideid=====================");
          print(rideId);
          navigatorKey.currentState?.pushNamed('/second');
        }
      });

     

      SharedPreferences prefs = await SharedPreferences.getInstance();
      
      emailAddress = prefs.getString('email').toString();
      token = prefs.getString('token').toString();
      emailAddress == "null" && token == "null"
          ? Navigator.of(context).pushAndRemoveUntil(
              MaterialPageRoute(builder: (context) => const PreLogin()),
              (route) => false)
          : role == "driver"
              ? Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (context) => DriverHome()),
                  (route) => false)
              : Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (context) => const UserHome()),
                  (route) => false);
    });

   
  }

  @override
  void dispose() {
    controller.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
          resizeToAvoidBottomInset: false,
          body: Container(
            decoration: const BoxDecoration(
              image: DecorationImage(
                image: AssetImage(splashBgImage),
                fit: BoxFit.fill,
              ),
            ),
            child: const Logo(),
          )),
    );
  }
}

please help me to fix this issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

玩物 2025-02-17 08:22:06

您的initstate()方法包含太多复杂的逻辑代码,需要重新格式化。

特定错误setState()在dispose()之后调用,因为该应用已更改为另一个页面,然后调用当前页面的setState()方法。

结合上面的代码,此代码片段将应用程序更改为另一个页面,


      SharedPreferences prefs = await SharedPreferences.getInstance();

      emailAddress = prefs.getString('email').toString();
      token = prefs.getString('token').toString();
      emailAddress == "null" && token == "null"
          ? Navigator.of(context).pushAndRemoveUntil(
              MaterialPageRoute(builder: (context) => const PreLogin()),
              (route) => false)
          : role == "driver"
              ? Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (context) => DriverHome()),
                  (route) => false)
              : Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (context) => const UserHome()),
                  (route) => false);

然后在此代码代码段

    Future.delayed(const Duration(seconds: 3), () async {
      FirebaseMessaging.onMessage.listen((RemoteMessage message) {
        print("onMessage Clicked!");

        String getId = message.data["id"];
        print("ride id get:    ${message.data["id"]}");
        if (mounted) {
          setState(() {
            bookedRideId =
                int.parse(getId); //this line is not wwrking, error points here
          });
        }
// ..

调用setState()方法。

Your initState() method contains too many complex logic codes and needs to be reformatted.

The specific error setState() called after dispose() occurs because the app has changed to another page before calling the setState() method of the current page.

Combined with the code above, this code snippet changes the app to another page


      SharedPreferences prefs = await SharedPreferences.getInstance();

      emailAddress = prefs.getString('email').toString();
      token = prefs.getString('token').toString();
      emailAddress == "null" && token == "null"
          ? Navigator.of(context).pushAndRemoveUntil(
              MaterialPageRoute(builder: (context) => const PreLogin()),
              (route) => false)
          : role == "driver"
              ? Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (context) => DriverHome()),
                  (route) => false)
              : Navigator.of(context).pushAndRemoveUntil(
                  MaterialPageRoute(builder: (context) => const UserHome()),
                  (route) => false);

before this code snippet

    Future.delayed(const Duration(seconds: 3), () async {
      FirebaseMessaging.onMessage.listen((RemoteMessage message) {
        print("onMessage Clicked!");

        String getId = message.data["id"];
        print("ride id get:    ${message.data["id"]}");
        if (mounted) {
          setState(() {
            bookedRideId =
                int.parse(getId); //this line is not wwrking, error points here
          });
        }
// ..

which calls the setState() method.

烟沫凡尘 2025-02-17 08:22:06

如果要setState({})匿名喜欢从提供商广播播放器侦听器回调,则必须等待窗口小部件安装,但是某个时间

if(nocted){// code} {// code}不足以执行此功能,因此会导致内存泄漏问题。解决方案是创建一个异步函数以运行您的代码并从那里设置状态。小部件的生命周期必须一直遵守。任何匿名请求对另一个小部件中的状态进行调整等待,直到安装了小部件,因此您必须延迟setState({})fotr几秒钟,然后检查窗口小部件已安装,然后设置状态。假设您使用提供商将消息设置为流订阅以设置某个状态,请说未来,您的代码看起来像这样

import 'package:flutter/material.dart';

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

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
 late  Future<demo> demoFuture;
   late StreamSubscription uiSubscription;
  @override
  void initState() {

    // TODO: implement initState
    super.initState();
    demoFuture = getDemoFuture();
       final applicationBloc =
        Provider.of<MyDemoBloc>(context, listen: false);
    uiSubscription = applicationBloc.uiCommunication.stream
        .asBroadcastStream()
        .listen((message) async {
updateMyFuture();

        });
  }

  void updateMyFuture(){
    /// your code
       Future.delayed(const Duration(seconds: 2), () async {
           setState(() {
              demoFuture = getDemoFuture();
           });
       });
  }
  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

if you want to setState({}) anonymously like from provider broadcastStream listener callback, you must wait for your widget to be mounted, but some time

if(mounted){// your code } isn't enough to do the trick so it will cause a memory leak problem. the solution is to create an async function to run your code and set state from there. the life cycle of a widget must be obeyed all the time. Any anonymous request to sate state in another widget wait untill that widget is mounted so you must delay setState({}) fotr a few seconds and check the widget is mounted, then set state. Lets say your using provider to set a message to a stream subscription to set a certain state lets say a future, your code would look like this

import 'package:flutter/material.dart';

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

  @override
  State<MyWidget> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
 late  Future<demo> demoFuture;
   late StreamSubscription uiSubscription;
  @override
  void initState() {

    // TODO: implement initState
    super.initState();
    demoFuture = getDemoFuture();
       final applicationBloc =
        Provider.of<MyDemoBloc>(context, listen: false);
    uiSubscription = applicationBloc.uiCommunication.stream
        .asBroadcastStream()
        .listen((message) async {
updateMyFuture();

        });
  }

  void updateMyFuture(){
    /// your code
       Future.delayed(const Duration(seconds: 2), () async {
           setState(() {
              demoFuture = getDemoFuture();
           });
       });
  }
  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文