You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

点击按钮延迟4秒更新Cubit状态,出现BlocProvider找不到TestCubit报错

问题与解决方案

我希望点击按钮后4秒更新Cubit的状态,但触发了以下错误:

BlocProvider.of() called with a context that does not contain a TestCubit.
======== 手势处理捕获到异常 ===============================================================
处理手势时抛出以下断言:
        BlocProvider.of() 被传入的context中不包含TestCubit。
        从传入BlocProvider.of<TestCubit>()的context开始,未找到任何祖先组件。
        这种情况可能是因为你使用的context来自BlocProvider上方的widget。
        使用的context为: MyHomePage(state: _MyHomePageState#ea89e)
        
抛出异常时的调用栈:
#0      BlocProvider.of (package:flutter_bloc/src/bloc_provider.dart:103:7)
#1      _MyHomePageState.build.<anonymous closure> (package:flutter_cubit/main.dart:58:34)
#2      _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1072:21)
#3      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:253:24)
#4      TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:627:11)
#5      BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:306:5)
#6      BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:239:7)
#7      PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:615:9)
#8      PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:98:12)
#9      PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:143:9)
#10     _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:617:13)
#11     PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:141:18)
#12     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:127:7)
#13     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:460:19)
#14     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:440:22)
#15     RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:337:11)
#16     GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:395:7)
#17     GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:357:5)
#18     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:314:7)
#19     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:295:7)
#20     _invoke1 (dart:ui/hooks.dart:167:13)
#21     PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:341:7)
#22     _dispatchPointerDataPacket (dart:ui/hooks.dart:94:31)
Handler: "onTap"
Recognizer: TapGestureRecognizer#97fe2
  debugOwner: GestureDetector
  state: possible
  won arena
  finalPosition: Offset(188.3, 443.5)
  finalLocalPosition: Offset(30.8, 20.5)
  button: 1
  sent tap down

问题原因

当前代码中,BlocProvider和ElevatedButton是Column的同级子组件,按钮使用的context来自MyHomePage,而BlocProvider是MyHomePage的子节点,因此按钮的上下文无法找到TestCubit实例。此外,TestState的子类未正确实现props方法,运行时会抛出未实现错误。

修正后的代码

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_cubit/bloc/test_cubit.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Cubit Bloc'),
      ),
      body: Center(
        // 将BlocProvider移到Column外层,让按钮处于其上下文范围内
        child: BlocProvider(
          create: (_) => TestCubit(),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              BlocBuilder<TestCubit, TestState>(
                builder: (context, state) {
                  if (state is Loading) {
                    return const CircularProgressIndicator();
                  } else if (state is Loaded) {
                    return const Text('Loaded');
                  }
                  return const Text('Error');
                },
              ),
              ElevatedButton(
                onPressed: () {
                  BlocProvider.of<TestCubit>(context).getData();
                },
                child: const Text('Click')
              )
            ],
          ),
        ),
      )
    );
  }
}

test_cubit.dart

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';

part 'test_state.dart';

class TestCubit extends Cubit<TestState> {

  TestCubit() : super(Loading());

  Future<void> getData() async {
    try {
      emit(Loading());
      await Future.delayed(const Duration(seconds: 4));
      emit(Loaded());
    } catch (e) {
      emit(ErrorException());
    }
  }
}

test_state.dart

part of 'test_cubit.dart';

abstract class TestState extends Equatable {
  const TestState();
}

class Loading extends TestState {
  const Loading();
  @override
  List<Object?> get props => [];
}

class Loaded extends TestState {
  const Loaded();

  @override
  List<Object?> get props => [];
}

class ErrorException extends TestState {
  const ErrorException();

  @override
  List<Object?> get props => [];
}

关键修改点

  1. 将BlocProvider移动到Column的外层,确保按钮和BlocBuilder都处于BlocProvider的上下文范围内,这样按钮就能通过context获取到TestCubit实例。
  2. 实现TestState子类的props方法,返回空列表(因为这些状态没有需要比较的属性),避免运行时抛出未实现错误。

内容的提问来源于stack exchange,提问作者user20393696

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 16:35:18