Home > database >  How to change state of cubit?
How to change state of cubit?

Time:12-28

image description here

I want to change the state of cubit after 4 seconds when i click the button but it gives error :

**BlocProvider.of() called with a context that does not contain a TestCubit.
======== Exception caught by gesture ===============================================================
The following assertion was thrown while handling a gesture:
        BlocProvider.of() called with a context that does not contain a TestCubit.
        No ancestor could be found starting from the context that was passed to BlocProvider.of<TestCubit>().
        This can happen if the context you used comes from a widget above the BlocProvider.
        The context used was: MyHomePage(state: _MyHomePageState#ea89e)
        
When the exception was thrown, this was the stack: 
#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**

My code here:

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: Text('Cubit Bloc'),
      ),
      body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              BlocProvider(
                create: (_) => TestCubit(),
                child: BlocBuilder<TestCubit, TestState>(
                  builder: (context, state) {
                    if (state is Loading) {
                      return CircularProgressIndicator();
                    } else
                    if (state is Loaded) {
                      return Text('Loaded');
                    }
                    return Text('Error');
                  },
                ),
              ),
              ElevatedButton(
                  onPressed: () {
                    BlocProvider.of<TestCubit>(context).getData();
                  },
                  child: Text('Click')
              )
            ],
          )
      )
    );
  }
}

test_cubit

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(Duration(seconds: 4));
      emit(Loaded());
    } catch (e) {
      emit(ErrorException());
    }
  }
}

test_state

part of 'test_cubit.dart';

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

class Loading extends TestState {
  const Loading();
  @override
  // TODO: implement props
  List<Object?> get props => throw UnimplementedError();
}

class Loaded extends TestState {
  const Loaded();

  @override
  // TODO: implement props
  List<Object?> get props => throw UnimplementedError();
}

class ErrorException extends TestState {
  const ErrorException();

  @override
  // TODO: implement props
  List<Object?> get props => throw UnimplementedError();
}

CodePudding user response:

You have two ways to do this. Firstly please keep remind that BlocProvider.of only finds that bloc object which is top of widget tree. You are putting TestBloc() in the peer widget. The widget you attach TestBloc() should cover the place which you are using BlocProvider.of

**IMPORTANT: ** But I prefer the other way as it is pretty easy to understand

Declare var testBloc=TestBloc(); outside of build method inside the widgetState class. Then instead of BlocProvider.of use testBloc.someMethod. Don’t forget to put it here too:

BlocProvider(
   create: (_) => testCubit,

CodePudding user response:

you are using BlocProvider in the wrong scope, try moving BlocProvider outside of MyHomePage class

try this:

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 BlocProvider(
      create: (context) => TestCubit(),
      child: 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: Text('Cubit Bloc'),
        ),
        body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                BlocBuilder<TestCubit, TestState>(
                  builder: (context, state) {
                    if (state is Loading) {
                      return CircularProgressIndicator();
                    } else if (state is Loaded) {
                      return Text('Loaded');
                    }
                    return Text('Error');
                  },
                ),
                ElevatedButton(
                    onPressed: () {
                      BlocProvider.of<TestCubit>(context).getData();
                    },
                    child: Text('Click')
                )
              ],
            )
        )
    );
  }
}
  • Related