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

Flutter导航动画卡顿求助:HTTP请求提前返回致UI切换干扰

解决Flutter导航动画卡顿:等待动画完成后发起HTTP请求

这个问题我之前也遇到过!核心原因就是页面导航的过渡动画还在执行时,UI突然因为HTTP请求完成而更新,两者抢GPU资源导致卡顿。下面给你一个可靠的解决方案,确保请求只会在导航动画彻底完成后才发起:

思路说明

我们需要把HTTP请求的触发时机从页面构建时,延迟到导航过渡动画完全结束之后。具体实现上,我们可以用StreamController来手动控制数据流,在确认动画完成后再发起请求并将结果注入流中,这样StreamBuilder就只会在合适的时机更新UI。

修改后的NewPage代码

class _NewPageState extends State<NewPage> {
  late StreamController<Model> _dataController;

  @override
  void initState() {
    super.initState();
    _dataController = StreamController<Model>();
    // 等待页面首次渲染完成后,监听导航动画状态
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _waitForNavigationAnimationThenFetch();
    });
  }

  void _waitForNavigationAnimationThenFetch() {
    final currentRoute = ModalRoute.of(context);
    if (currentRoute?.animation != null) {
      // 监听动画状态,当动画完成时发起请求
      currentRoute!.animation!.addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          _fetchData();
        }
      });
    } else {
      // 没有过渡动画(比如直接pushReplacement的情况),直接发起请求
      _fetchData();
    }
  }

  void _fetchData() {
    Repository().getItem(widget.id).listen(
      (model) => _dataController.add(model),
      onError: (error) => _dataController.addError(error),
    );
  }

  @override
  void dispose() {
    _dataController.close(); // 记得关闭控制器,避免内存泄漏
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: StreamBuilder(
        // 改为使用我们自己的控制器流
        stream: _dataController.stream,
        builder: (context, AsyncSnapshot<Model> itemsSnapshot) {
          if (itemsSnapshot.hasError) {
            return ErrorWigets();
          }
          // 初始状态(请求未发起)也显示Spinner
          if (!itemsSnapshot.hasData) {
            return Spinner();
          }
          return ListView(
            children: <Widget>[
              // 页面内容
            ],
          );
        },
      ),
    );
  }
}

代码解释

  1. StreamController:用来手动控制数据的发射时机,替代原来直接从Repository获取流的方式,让我们能完全掌控请求发起时间。
  2. addPostFrameCallback:确保我们在页面首次渲染完成后再去监听动画状态,避免过早获取路由动画导致的空指针问题。
  3. 动画状态监听:通过ModalRoute.of(context)获取当前路由的动画,监听其AnimationStatus.completed状态,确认动画彻底结束后再调用_fetchData发起HTTP请求。
  4. 资源清理:在dispose方法中关闭StreamController,避免内存泄漏。

这样修改后,不管HTTP请求响应有多快,都会等导航动画完全结束后才更新UI,彻底解决动画卡顿的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:44:17