Bloc 监听器未触发

问题描述 投票:0回答:2

我有一个登录屏幕。单击徽标时,我想在其顶部显示一个加载项。我放入的加载小部件

ContainerWithLoadingOverlay
.

main.dart

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(create: (_) => sl<OverlayLoadingCubit>()),
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        localizationsDelegates: [
          EasyLocalization.of(context)!.delegate,
        ],
        supportedLocales: EasyLocalization.of(context)!.supportedLocales,
        locale: EasyLocalization.of(context)!.locale,
        title: kAppTitle,
        theme: AppTheme.light,
        onGenerateRoute: AppRoute.onGenerateRoutes,
      ),
    );
  }
}

log_in_screen.dart

 return Scaffold(
        body: ContainerWithLoadingOverlay(    <--- this for loading 
      child: SingleChildScrollView(
          child: Padding(
              padding: const EdgeInsets.all(32.0),
              child: Center(
                child: Column(
                  children: [
                    const AppLogo(
                      width: 150,
                      height: 150,
                    ),
                    const SizedBox(height: 32),
                    InkWell(
                        onTap: () {
                          context.read<LogInCubit>().signIn(
                              SignInParams(
                                  email: _emailController.text,
                                  password: _passwordController.text));
                        },
                        child: Text(
                          "Welcome back.",
                          style: Theme.of(context).textTheme.headline4,
                        )),
                    const SizedBox(height: 32),
                    // _loginForm(context, isShown),
                  ],
                ),
              ))),
    ));
  }

log_in_cubit.dart

class LogInCubit extends Cubit<LogInState> {
  final OverlayLoadingCubit _loadingCubit;
  final SignInUseCase _useCase;

  LogInCubit(this._useCase, this._loadingCubit) : super(LogInLoading());

  Future<void> signIn(SignInParams params) async {
    _loadingCubit.startLoading();  
           ...
  }
}

overlay_loading_state.dart

part of 'overlay_loading_cubit.dart';

abstract class OverlayLoadingState {
  const OverlayLoadingState();
}

class OverlayLoadingInitial extends OverlayLoadingState {}

class IsLoadingState extends OverlayLoadingState {}

overlay_loading_cubit.dart

class OverlayLoadingCubit extends Cubit<OverlayLoadingState> {
  OverlayLoadingCubit() : super(OverlayLoadingInitial());

   startLoading() {
    debugPrint("start loading");  <-- this line is able to print
    emit(IsLoadingState());  
    return;
  }
}

container_with_loading_overlay.dart

class ContainerWithLoadingOverlay extends HookWidget {
  final Widget child;

  const ContainerWithLoadingOverlay({Key? key, required this.child})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocListener<OverlayLoadingCubit, OverlayLoadingState>(
      listener: (context, state) {
        debugPrint("call from listener");  <--- this line not calling
        if (state is OverlayLoadingInitial) {
          context.loaderOverlay.hide();
        }

        if (state is IsLoadingState) {
          context.loaderOverlay.show();
        }
      },
      child: LoaderOverlay(
        useDefaultLoading: false,
        overlayWidget: const Center(child: CircularProgressIndicator()),
        child: child,
      ),
    );
  }
}

我希望课堂上的 bloc 监听器

ContainerWithLoadingOverlay
会被触发并显示加载对话框,但它不会被触发..有什么问题吗?

flutter dart listener bloc
2个回答
0
投票

BlocListener 只有在检测到状态变化时才会被触发。如果您的 BlocListener 没有被触发,请尝试先发出 OverlayLoadingInitial() 状态,等待一秒钟,然后发出 isLoadingStates 状态。

这是一个示例代码:

void startLoading() {
  // debugPrint("start loading");  <-- this line is able to print
  emit(OverlayLoadingInitial());
  await Future.delayed(const Duration(seconds: 1)); // Emulates your signIn request
  emit(IsLoadingState());
  return;
}

0
投票

问题是由

DI
引起的,
overlayLoadingCubit
的实例在应用程序的不同部分是不一样的,因为你可以使用
Bloc
作为依赖注入器,在这种情况下不需要使用
DI

你可以这样改变

app.dart

class App extends StatelessWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    OverlayLoadingCubit overlayLoadingCubit = OverlayLoadingCubit();
    LogInCubit logInCubit = LogInCubit(overlayLoadingCubit);

    return MultiBlocProvider(
      providers: [
        BlocProvider(create: (_) => overlayLoadingCubit),
        BlocProvider(create: (_) => logInCubit),
      ],
      child: const MaterialApp(
        debugShowCheckedModeBanner: false,
        title: "Sample",
        onGenerateRoute: AppRoute.onGenerateRoutes,
      ),
    );
  }
}

另外,无需在

OverlayLoadingCubit
中提供
app_route.dart

class AppRoute {
  static const loginScreen = '/loginPage';

  static MaterialPageRoute<dynamic> _loginScreenRoute() =>
      MaterialPageRoute(builder: (context) => const LogInScreen());

  static Route? onGenerateRoutes(RouteSettings settings) => _loginScreenRoute();
}
© www.soinside.com 2019 - 2024. All rights reserved.