如何在BlocBuilder Flutter中延迟返回屏幕

时间:2020-04-26 06:49:50

标签: flutter bloc

在我的应用中,我使用flutter_bloc进行状态管理,在main()中使用BlocBuilder进行身份验证,如果它收到Authenticated状态,则会返回MapScreen,如果状态为Unauthenticated,则返回LoginScreen,否则返回Splashscreen。我想控制Splashscreen的显示时间,所以我尝试在BlocBuilder的内部状态检查中添加一个计时器,但是它从不返回屏幕。如何设置Splashscreen在一定时间内保持可见状态? 一如既往的感谢您的时间和帮助。 这是BlocBuilder

home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
        builder: (context, state) {
          if (state is Unauthenticated) {
//            Timer(Duration(seconds: 10), () {
            return LoginScreen(userRepository: _userRepository);
//            });
          }
          if (state is Authenticated) {
//            Timer(Duration(seconds: 50), () {
            return MultiBlocProvider(
              providers: [
                BlocProvider<DefaultsBloc>(
                  lazy: false,
                  create: (context) => DefaultsBloc()..add(InitializeRemote()),
                ),
                BlocProvider<TrackingBloc>(
                  create: (context) => TrackingBloc(),
                ),
                BlocProvider<DirectionsBloc>(
                  create: (context) => DirectionsBloc(),
                ),
                BlocProvider<GeoBloc>(
                  create: (context) => GeoBloc(),
                ),
                BlocProvider<RouteBloc>(
                  lazy: false,
                  create: (context) => RouteBloc(),
                ),
                BlocProvider<SchedulerBloc>(
                  create: (context) => SchedulerBloc(),
                ),
                BlocProvider<CheckerBloc>(
                  create: (context) => CheckerBloc(),
                ),
                BlocProvider<LocationBloc>(
                    lazy: false,
                    create: (context) => LocationBloc(
                          mapRepository: _mapRepository,
                        )
                          ..add(GetLocationStream())
                          ..add(GetLocation())
                          ..add(GetIsoLocationUser())),
                BlocProvider<AlertBloc>(
                  create: (context) => AlertBloc(
                      alertRepository: _alertRepository, user: state.user),
                ),
                BlocProvider<LocalNotificationBloc>(
                  lazy: false,
                  create: (context) => LocalNotificationBloc(),
                )
              ],
              child: MapScreen(
//                mapRepository: _mapRepository,
                user: state.user,
//              alertRepository: FirebaseAlertRepository(),
              ),
            );
//            });
          }
          return SplashScreen();
        },
      ),

2 个答案:

答案 0 :(得分:1)

我必须先创建一个新事件StartApp,然后将其发送到bloc,然后在bloc中设置一个计时器,以添加AppStarted事件以启动所有身份验证逻辑。

Stream<AuthenticationState> mapEventToState(
      AuthenticationEvent event) async* {
    if (event is StartApp) {
      yield* _startAppToState();
    }
    if (event is AppStarted) {
      yield* _mapAppStartedToState();
    } else if (event is LoggedIn) {
      yield* _mapLoggedInToState();
    } else if (event is LoggedOut) {
      yield* _mapLoggedOutToState();
    }
  }

  Stream<AuthenticationState> _startAppToState() async* {
    Timer(Duration(seconds: 5), () {
      add(AppStarted());
    });
  }

  Stream<AuthenticationState> _mapAppStartedToState() async* {
    try {
      final isSignedIn = await _userRepository.isSignedIn();
      if (isSignedIn) {
        final user = await _userRepository.getUser();
        yield Authenticated(user);
      } else {
        yield Unauthenticated();
      }
    } catch (_) {
      yield Unauthenticated();
    }
  }

我希望这会帮助其他人。 干杯。

答案 1 :(得分:0)

您不能在构建方法中使用计时器。您可以创建一个新的StatefulWidget,然后在initState中添加一个计时器,以导航到下一个屏幕,该屏幕将是您当前用于家庭的窗口小部件。

import 'dart:async';

import 'package:flutter/material.dart';

class Splash extends StatefulWidget {
  @override
  _SplashState createState() => _SplashState();
}

class _SplashState extends State<Splash> {
  @override
  void initState() {
    super.initState();
    Timer(
      const Duration(seconds: 1),
      () => Navigator.of(context).pushReplacement(
        MaterialPageRoute(builder: (context) => OtherScreen()),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Text('Splash'),
      ),
    );
  }
}