You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中Navigator Pop页面后函数仍运行,如何彻底销毁页面与函数?

Flutter页面pop后while循环仍持续执行的解决方法

问题描述

从NextScreen页面通过Navigator.pop返回HomeScreen后,预期页面会被销毁且所有关联函数停止运行,但实际startLoopStatus中的while循环仍在持续执行,导致Config.count不断增加、相关日志持续输出。

问题原因

  1. 循环的终止条件status == false && isCurrentStatus未与页面生命周期绑定,页面销毁时没有修改这两个变量,循环会一直满足条件继续执行。
  2. Dart的异步任务一旦启动,会在事件队列中持续运行,直到循环条件不满足,不会因为页面State被dispose而自动停止。

解决方案

在页面的dispose方法中修改循环控制变量,主动终止while循环:

修改后的完整代码

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class Config {
  static int count = 0;
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const HomeScreen(),
    );
  }
}

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

  @override
  State<NextScreen> createState() => _NextScreenState();
}

class _NextScreenState extends State<NextScreen> {
  int timerCount = 0;
  bool status = false;
  bool isCurrentStatus = true;

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

  void getInit() {
    try {
      WidgetsBinding.instance.addPostFrameCallback((_) async {
        startLoopStatus();
      });
    } catch (e) {
      print('[getInit] ERROR:: $e');
    }
  }

  Future<void> startLoopStatus() async {
    print('[startLoopStatus] Running startLoopStatus 001.');
    print(isCurrentStatus);
    while (status == false && isCurrentStatus) {
      if (mounted) {
        setState(() {
          timerCount += 1;
        });
      }

      await Future.delayed(const Duration(seconds: 2), () {
        debugPrint("delay----------");
        Config.count += 1;
        print(Config.count);
      });
      await loopArrive();
    }
    print('[startLoopStatus] Loop terminated.');
  }

  Future<void> loopArrive() async {
    print('[loopArrive] Running loopArrive 001.');
    print('[loopArrive] timerCount: $timerCount');
    try {
      if (mounted && ModalRoute.of(context)!.isCurrent) {
        print('[loopArrive] Running loopArrive 002.');
      }
    } catch (e) {
      print('[loopArrive] ERROR:: $e');
    }
  }

  @override
  void dispose() {
    print('[NextScreen] dispose()');
    // 修改控制变量,终止while循环
    isCurrentStatus = false;
    status = true;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Next'),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
      ),
      body: const SafeArea(
        child: Center(
          child: Column(
            children: [
              Text('Please see the terminal output.'),
            ],
          ),
        ),
      ),
    );
  }
}

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home'),
      ),
      body: SafeArea(
        child: Center(
          child: Column(
            children: [
              ElevatedButton(
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(builder: (_) => const NextScreen()),
                  );
                },
                child: const Text('Go to next page'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

关键修改点

  1. 在dispose方法中终止循环:

    @override
    void dispose() {
      print('[NextScreen] dispose()');
      isCurrentStatus = false;
      status = true;
      super.dispose();
    }
    

    这会让while循环的条件status == false && isCurrentStatus变为false,循环在下一次迭代时自动退出。

  2. 优化状态更新逻辑:
    移除了多余的Future.delayed(Duration.zero),直接在mounted判断内调用setState,简化代码逻辑。

  3. 添加循环终止日志:
    在startLoopStatus的while循环结束后添加日志,方便确认循环已终止。

内容的提问来源于stack exchange,提问作者chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 21:37:15