Блок навигации по изменению состояния - PullRequest
0 голосов
/ 13 февраля 2019

Я действительно новичок с блоками флаттера, и у меня возникли проблемы с реализацией блока, я пытаюсь перемещаться после изменения состояния в моем виджете заставки.

После обновления состояния до InitSuccess он должен перейти к LoginScreen , но эта навигация происходит много раз.

Я не могу понять, что делать после изменения состояния на InitSuccess , после этого блок продолжает жить и звонить много, много раз LoginScreen .

Экран-заставка

class SplashScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  SplashBloc _splashBloc;
  final _scaffoldKey = GlobalKey<ScaffoldState>();

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

  @override
  void dispose() {
    _splashBloc.dispose();
    super.dispose();
  }

  void _init() {
    Future.delayed(Duration.zero, () {
      checkDeviceConnection(context);
      BlocSupervisor().delegate = SplashBlocDelegate();
      final bool isIOS = Theme.of(context).platform == TargetPlatform.iOS;
      _splashBloc = SplashBloc(
        firebaseService: FirebaseService(context),
        authService: AuthService(context),
        devicesService: DevicesService(context),
      );
      _splashBloc.dispatch(SplashInitEvent(isIOS: isIOS));
    });

@override
  Widget build(BuildContext context) {
    SystemChrome.setEnabledSystemUIOverlays([]);
    return BlocBuilder<SplashEvent, SplashState>(
      bloc: _splashBloc,
      builder: (
        BuildContext context,
        SplashState state,
      ) {
        if (state is InitFailure) {
          Future.delayed(Duration.zero, () {
            showWarningSnackBar(_scaffoldKey, state.error);
          });
        }

        if (state is InitSuccess) {
          Future.delayed(Duration.zero, () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => LoginScreen(),
              ),
            );
          });
        }

        return Scaffold(
          key: _scaffoldKey,
          body: Container(
            decoration: appScreenGradient,
            alignment: Alignment.center,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Image.asset(
                  "assets/images/splash_screen/logo_splash.png",
                  width: 172.88,
                  height: 144.55,
                  fit: BoxFit.contain,
                ),
                SizedBox(
                  height: 20.0,
                ),
                LoadingSpinner(
                  spinnerColor: Theme.of(context).primaryColorLight,
                ),
              ],
            ),
          ),
        );
      },
    );
  }

Блок-заставка

class SplashBloc extends Bloc<SplashEvent, SplashState> {
  final FirebaseService firebaseService;
  final DevicesService devicesService;
  final AuthService authService;
  final UserPreferences _userPreferences = UserPreferences();

  SplashBloc({
    @required this.firebaseService,
    @required this.devicesService,
    @required this.authService,
  });

  @override
  Stream<SplashEvent> transform(Stream<SplashEvent> events) {
    return (events as Observable<SplashEvent>).debounce(
        Duration(milliseconds: 500));
  }

  @override
  get initialState => SplashInitial();

  @override
  Stream<SplashState> mapEventToState(currentState, event) async* {
    if (event is SplashInitEvent) {
      if (currentState is SplashInitial) {
        yield InitLoading();

        try {
          firebaseService.togglePerformanceCollection(true);
          firebaseService.firebaseCloudMessagingListeners();

          String firebaseToken = await firebaseService
              .getFirebaseMessagingToken();
          bool isRegistered =
              await _userPreferences.getIsDeviceRegistered() ?? false;

          if (!isRegistered) {
            final String platform = event.isIOS ? 'IOS' : 'Android';
            final deviceInfo = await devicesService.getDeviceInfo(platform);
            isRegistered = await devicesService.register(
              deviceToken: firebaseToken,
              deviceInfo: deviceInfo,
            );
            if (isRegistered) {
              _userPreferences.setIsDeviceRegistered(true);
            }
          }

          yield InitSuccess();
        } catch (e) {
          yield InitFailure(error: e.toString());
        }
      }
    }

    if (event is SplashInitialEvent) {
      yield SplashInitial();
    }
  }
}

1 Ответ

0 голосов
/ 09 апреля 2019

Я нашел следующее решение:

if (state is LoggedIn) {
  WidgetsBinding.instance.addPostFrameCallback((_) { 
    // Navigation
  });
}

Я обернул навигацию этим обратным вызовом addPostFrame для задержки его появления.

...