skip to Main Content

I have this code. In summary, I am learning Flutter and I created this code just to practice. The goal is to type in a TextField and then press a FloatingActionBotton and onPressed it updates a text widget. I used BloC as a state manager. Then, just to test Flutter behavior, I created a new screen to go back and forth and see it works. I was surprise to see that I lost my state in my home page and that I can’t even update the text widget anymore after pressing the FloatingActionButton. What happened?

When I come back to home screen, the text widget is gone and when I press the floatingactionbutton (add icon) I get an exception BlocProvider.of() called with a context that does not contain a ExampleBloc.

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';

void main() {
  runApp(MaterialApp(
    home: BlocProvider.value(
      value: ExampleBloc(),
      child: Home(),
    ),
  ));
}

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

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  late TextEditingController teste;
  late String lol;

  @override
  void initState() {
    teste = TextEditingController();
    lol = 'ola';
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: Column(
        children: <Widget>[
          TextField(
            controller: teste,
          ),
          Center(child: BlocBuilder<ExampleBloc, ExampleState>(
            builder: (context, state) {
              return Text(state.exampleString ?? 'null');
            },
          ))
        ],
      ),
      floatingActionButton: Row(
        children: [
          FloatingActionButton(
            onPressed: () {
              lol = teste.text;
              BlocProvider.of<ExampleBloc>(context)
                  .add(ExampleUseEvent(exampleString: lol));
            },
            child: Icon(Icons.add),
          ),
          FloatingActionButton(
            onPressed: () => Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => HEHE()),
            ),
            child: Text('next screen'),
          ),
          FloatingActionButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('pop'),
          ),
        ],
      ),
    );
  }

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

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: const Center(child: Text('teste')),
      floatingActionButton: Row(
        children: [
          FloatingActionButton(
              onPressed: () => Navigator.of(context).push(
                    MaterialPageRoute(builder: (context) => Home()),
                  ),
              child: Text('next screen')),
        ],
      ),
    );
  }
}

class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
  ExampleBloc() : super(ExampleState()) {
    on<ExampleUseEvent>(exampleFuncion);
  }

  Future<void> exampleFuncion(
    ExampleUseEvent event,
    Emitter<ExampleState> emit,
  ) async {
    emit(state.copyWith(
      exampleString: event.exampleString,
    ));
  }
}

abstract class ExampleEvent {}

class ExampleUseEvent extends ExampleEvent {
  final String exampleString;

  ExampleUseEvent({required this.exampleString});
}

class ExampleState extends Equatable {
  final String? exampleString;

  ExampleState({
    this.exampleString,
  });

  ExampleState copyWith({
    String? exampleString,
  }) {
    return ExampleState(
      exampleString: exampleString ?? this.exampleString,
    );
  }

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

2

Answers


  1. Look how I use bloc in Flutter, I think your error is because you don’t have a state of your bloc, so, the data reset.

    example_state.dart

    import 'package:equatable/equatable.dart';
    
    class ExampleState extends Equatable {
      final String? exampleString;
      
      ExampleState ({
        this.exampleString,
      });
      
       ExampleState copyWith({
        String? exampleString,
      }){
        return ExampleState(
          exampleString: exampleString?? this.exampleString,
        );
      }
    
      @override
      List<Object?> get props => [
        exampleString,
      ];
    }
    

    example_bloc.dart

    class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
    
      ExampleBloc() : super(ExampleState()) {
        on<ExampleUseEvent>(exampleFuncion);
      }
    
      Future<void> exampleFuncion(
        ExampleUseEvent event,
        Emitter<ExampleState> emit,
      ) async {
        emit(state.copyWith(
          exampleString: event.exampleString,
        ));
      }
    }
    

    example_event.dart

    abstract class ExampleEvent {}
    
    class ExampleUseEvent extends ExampleEvent {
      final String exampleString;
    
      ExampleUseEvent({required this.exampleString});
    }
    
    Login or Signup to reply.
  2. Example bloc only exists in fist page when it is provided by MaterialApp.

    Switch MaterialApp and BlocProvider.value to get the desired result.

    MaterialApp contains Navigator which contains list of PageRoutes when pages are pushed. If BlocProvider will be defined before MaterialApp, it will be available to all the pages.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search