首页 > 解决方案 > 在我的肘部发出变化状态不会为我的听众产生事件

问题描述

我的屏幕如下所示:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:app/flows/splashscreen/splash_screen_cubit.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:rflutter_alert/rflutter_alert.dart';

class SplashScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocConsumer<SplashScreenCubit, SplashScreenState>(
        listener: (context, state) {
      debugPrint("listener received something");
      if (state is SplashScreenCheckingToken) {
        debugPrint("state is SplashScreenCheckingToken");
        context.bloc<SplashScreenCubit>().checkingAccessToken();
      } else if (state is SplashScreenTokenValid) {
        Navigator.pushNamed(context, '/home');
      } else if (state is SplashScreenTokenInvalid) {
        Navigator.pushNamed(context, '/landing-page');
      } else if (state is SplashScreenError) {
        _showError(context);
      }
    }, builder: (context, state) {
      if (state is SplashScreenInitial) {
        debugPrint("state is SplashScreenInitial");
        context
            .bloc<SplashScreenCubit>()
            .checkAccessToken(); // doesn't work, but why?
        // context.bloc<SplashScreenCubit>().checkingAccessToken(); // works
        return Scaffold(
            body:
                Container(color: Colors.green, child: _loadingWidget(context)));
      } else {
        return Container();
      }
    });
  }

  SpinKitChasingDots _loadingWidget(BuildContext context) {
    return SpinKitChasingDots(
      color: Colors.white,
      size: 50.0,
    );
  }

  Future<bool> _showError(BuildContext context) {
    return Alert(context: context, title: "Error", desc: "Something went wrong")
        .show();
  }
}

我的肘部是这样的:

import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:app/repository/api_repository.dart';
part 'splash_screen_state.dart';

class SplashScreenCubit extends Cubit<SplashScreenState> {
  final APIRepository _apiRepository;

  SplashScreenCubit(this._apiRepository) : super(SplashScreenInitial());

  void checkAccessToken() {
    debugPrint("checkAccessToken begin");
    emit(SplashScreenCheckingToken());
    debugPrint("checkAccessToken finished");
  }

  Future<void> checkingAccessToken() async {
    try {
      final quote = await _apiRepository.fetchQuote();
      debugPrint(quote.toString());
      emit(SplashScreenTokenValid());
    } on Error {
      emit(SplashScreenError());
    }
  }

  void accessTokenValid() {
    emit(SplashScreenTokenValid());
  }

  void accessTokenInvalid() {
    emit(SplashScreenTokenInvalid());
  }
}

我的状态如下:

part of 'splash_screen_cubit.dart';

enum SplashScreenStateEnum {
  Initial,
  CheckingToken,
  TokenValid,
  TokenInvalid,
  Error,
}

abstract class SplashScreenState {
  final SplashScreenStateEnum splashScreenStateEnum;

  const SplashScreenState(this.splashScreenStateEnum);
}

class SplashScreenInitial extends SplashScreenState {
  const SplashScreenInitial() : super(SplashScreenStateEnum.Initial);
}

class SplashScreenCheckingToken extends SplashScreenState {
  const SplashScreenCheckingToken()
      : super(SplashScreenStateEnum.CheckingToken);

  @override
  bool operator ==(Object o) {
    if (identical(this, o)) return true;

    return o is SplashScreenCheckingToken &&
        o.splashScreenStateEnum == splashScreenStateEnum;
  }

  @override
  int get hashCode => splashScreenStateEnum.hashCode;
}

class SplashScreenTokenValid extends SplashScreenState {
  const SplashScreenTokenValid() : super(SplashScreenStateEnum.TokenValid);

  @override
  bool operator ==(Object o) {
    if (identical(this, o)) return true;

    return o is SplashScreenTokenValid &&
        o.splashScreenStateEnum == splashScreenStateEnum;
  }

  @override
  int get hashCode => splashScreenStateEnum.hashCode;
}

class SplashScreenTokenInvalid extends SplashScreenState {
  const SplashScreenTokenInvalid() : super(SplashScreenStateEnum.TokenInvalid);

  @override
  bool operator ==(Object o) {
    if (identical(this, o)) return true;

    return o is SplashScreenTokenInvalid &&
        o.splashScreenStateEnum == splashScreenStateEnum;
  }

  @override
  int get hashCode => splashScreenStateEnum.hashCode;
}

class SplashScreenError extends SplashScreenState {
  const SplashScreenError() : super(SplashScreenStateEnum.Error);

  @override
  bool operator ==(Object o) {
    if (identical(this, o)) return true;

    return o is SplashScreenError &&
        o.splashScreenStateEnum == splashScreenStateEnum;
  }

  @override
  int get hashCode => splashScreenStateEnum.hashCode;
}

当我运行程序时,会打印以下内容:

flutter: state is SplashScreenInitial
flutter: checkAccessToken begin
flutter: checkAccessToken finished

这意味着尽管 Cubit 中的 checkAccessToken() 函数被触发,但 SplashScreen 上 BlocConsumer 的侦听器中没有事件进入。

否则它会打印:

"listener received something"

我不知道为什么,因为当我尝试 Cubit 中的 checksAccessToken() 函数时,这确实会为侦听器产生事件。

标签: flutterdartlistenerbloc

解决方案


SplashScreenCheckingToken负责所有其他“重定向”状态,但它从未被触发。也许你可以做的是在初始化之后修改你的cubit构造函数。

class SplashScreenCubit extends Cubit<SplashScreenState> {
  final APIRepository _apiRepository;

  SplashScreenCubit(this._apiRepository) : super(SplashScreenInitial()) {
    emit(SplashScreenCheckingToken());
  }

  ...
}

那应该解决它。


推荐阅读