如何在切换到新的小部件之前在StreamBuilder中添加延迟?

时间:2019-08-23 06:26:39

标签: flutter

我有StreamBuilder。我正在尝试用它做进度指示器。喜欢:

Loading token DONE
Loading regions DONE
Loading industry DONE

在最后一项之后(“ Loading industry DONE”),并切换到HomePage之前,我想添加一些延迟。但是我不明白该怎么做。我尝试使用Future.delayedTimer,但是使用它们切换到HomePage不会发生。没有延迟/计时器切换功能,但是我需要延迟之前。

这是我的代码:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/semantics.dart';
import 'package:provider/provider.dart';
import 'main.dart';

class SplashScreen extends StatefulWidget {
  SplashScreenState createState() => SplashScreenState();
}

class SplashScreenState extends State<SplashScreen> {
  String tokenLoadingState = '';
  String regionsLoadingState = '';
  String industryLoadingState = '';
  TenderApiProvider apiProv;

  @override
  Widget build(BuildContext context) {
    apiProv = Provider.of<TenderApiProvider>(context);
    return StreamBuilder(
        stream: apiProv.resultController,
        builder: (BuildContext context, AsyncSnapshot snapshot) {
          TenderApiProvider apiProv = Provider.of<TenderApiProvider>(context);

          if (snapshot.data is ApiKeyLoadingState) {
            switch (snapshot.data) {
              case ApiKeyLoadingState.Progress:
                tokenLoadingState = "Loading";
                break;
              case ApiKeyLoadingState.Done:
                tokenLoadingState = "Done";
                break;
              case ApiKeyLoadingState.Error:
                tokenLoadingState = "Error";
                break;
              default:
                return Text("Unknown");
            }
          } else if (snapshot.data is RegionsLoadingState) {
            switch (snapshot.data) {
              case RegionsLoadingState.Progress:
                regionsLoadingState = "Loading";
                break;
              case RegionsLoadingState.Done:
                regionsLoadingState = "Done";
                break;
              case RegionsLoadingState.Error:
                regionsLoadingState = "Error";
                break;
              default:
                return Text("Unknown");
            }
          } else if (snapshot.data is IndustryLoadingState) {
            switch (snapshot.data) {
              case IndustryLoadingState.Progress:
                industryLoadingState = "Loading";
                break;
              case IndustryLoadingState.Done:
                industryLoadingState = "Done";
                break;
              case IndustryLoadingState.Error:
                industryLoadingState = "Error";
                break;
              default:
                return Text("Unknown");
            }

            if (apiProv.apiKeyLoadingState == ApiKeyLoadingState.Done &&
                apiProv.regionsLoadingState == RegionsLoadingState.Done &&
                apiProv.industryLoadingState == IndustryLoadingState.Done) {

              Future.delayed(Duration(milliseconds: 1000)).then(
                  (_) => HomePage() // I need delay before switching to HomePage
              );

            }
          }

          return Scaffold(
              appBar: AppBar(),
              body: Center(
                  child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(
                    "Loading token: $tokenLoadingState",
                    textScaleFactor: 2,
                  ),
                  Text(
                    "Loading regions: $regionsLoadingState",
                    textScaleFactor: 2,
                  ),
                  Text(
                    "Loading industry: $industryLoadingState",
                    textScaleFactor: 2,
                  ),
                ],
              )));
        });
  }
}

2 个答案:

答案 0 :(得分:1)

您需要将逻辑移至build方法之外。 抖动中的build方法一定不能延迟,否则您的UI会滞后得很重。

对于您的用例,StreamBuilder可能不适合。它适合根据流的状态动态显示内容。它不适用于“路由”或“导航”,因为这会破坏小部件的构建过程。 这意味着,您必须手动订阅流。 这是一个例子。我无法测试它,因为您有许多隐藏的依赖项。

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

    SchedulerBinding.instance.addPostFrameCallback((_) {
      TenderApiProvider apiProv = Provider.of<TenderApiProvider>(context);
      apiProv.resultController.listen((data) async {
        if (apiProv.apiKeyLoadingState == ApiKeyLoadingState.Done &&
            apiProv.regionsLoadingState == RegionsLoadingState.Done &&
            apiProv.industryLoadingState == IndustryLoadingState.Done) {

          await Future.delayed(Duration(milliseconds: 1000));// I need delay before switching to HomePag
          Navigator.of(context).pushNamed('/home');

        }
      });

    });

  }

据我所知,您是新手,请考虑参加YouTube上现有的免费视频课程之一。

答案 1 :(得分:0)

尝试:

import 'dart:async';

Timer(const Duration(milliseconds: 1000), () => HomePage());