Как отложить возврат экрана в BlocBuilder Flutter - PullRequest
0 голосов
/ 26 апреля 2020

В моем приложении я использую 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 голосов
/ 26 апреля 2020

Мне нужно было создать новое событие StartApp, чтобы сначала отправить в blo c, а затем в blo c Я установил таймер, чтобы добавить событие AppStarted, которое запускает все логи аутентификации c .

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();
    }
  }

Надеюсь, это поможет другим. Приветствия.

0 голосов
/ 26 апреля 2020

Вы не можете использовать таймер в методе сборки. Вы можете создать новый 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'),
      ),
    );
  }
}
...