Search code examples
flutterdartflutter-dependenciesbloc

Problem with flutter widget update after state changes from bloc unless hot reloaded


So I am a native iOS developer who switched to flutter. Perhaps the problem I face currently with the bloc package has an easy fix but I have spent hours researching for a potential fix but have failed. This simple app i am building is simply a notes app. The issue i face is updating the UI based on a state change. Basically when i add a new item, the item gets added to the state but doesn't reflect in the Gridview.builder until i hot reload the app I threw all my frustrations on chatgpt just for it to keep on throwing gibberish responses.

My state

// ignore_for_file: public_member_api_docs, sort_constructors_first
part of 'note_bloc.dart';

abstract class NoteState extends Equatable {
  const NoteState();

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

class NoteInitial extends NoteState {}

//! App Initial State
class Notes extends NoteState {
  final List<NoteModel> noteList;

  const Notes(this.noteList);

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

My Events

// ignore_for_file: public_member_api_docs, sort_constructors_first
part of 'note_bloc.dart';

abstract class NoteEvent extends Equatable {
  const NoteEvent();

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

class DeletedNote extends NoteEvent {
  final int id;
  const DeletedNote({
    required this.id,
  });
}


class SavedNote extends NoteEvent {
  final String message;
  final DateTime time;

  const SavedNote({
    required this.message,
    required this.time,
  });
}

class EdittedNote extends NoteEvent {
  final String message;
  final DateTime time;

  const EdittedNote({
    required this.message,
    required this.time,
  });
}

My Bloc

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:notebook/data/model/note_model.dart';

part 'note_event.dart';
part 'note_state.dart';

class NoteBloc extends Bloc<NoteEvent, NoteState> {
  NoteBloc() : super(const Notes([])) {
    final List<NoteModel> noteModel = [];
    on<SavedNote>((event, emit) async {
      noteModel.add(NoteModel(noteModel.length + 1, event.time, event.message));
      await Future.delayed(const Duration(seconds: 1));
      emit(Notes(noteModel));
    });
  }
}

//! Since this project is a test project i packed everything in one file UI

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';

import 'blocs/bloc/note_bloc.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const BlocTestScreen());
}

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

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => NoteBloc(),
      child: PlatformApp(
        material: (context, platform) =>
            MaterialAppData(theme: ThemeData(useMaterial3: true)),
        home: const HomeScreen(),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return PlatformScaffold(
      appBar: PlatformAppBar(
        backgroundColor: Colors.amber,
        title: PlatformText('NoteBook'),
        trailingActions: [
          PlatformIconButton(
            onPressed: () {
              showPlatformDialog(
                  context: context,
                  builder: (context) {
                    return PlatformAlertDialog(
                      actions: [
                        Padding(
                          padding: const EdgeInsets.all(20.0),
                          child: PlatformElevatedButton(
                            child: const Text('Save'),
                            onPressed: () {
                              BlocProvider.of<NoteBloc>(context).add(SavedNote(
                                  message: 'message', time: DateTime.now()));
                              Navigator.pop(context);
                            },
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.all(20.0),
                          child: PlatformElevatedButton(
                            child: const Text('Cancel'),
                            onPressed: () {
                              Navigator.pop(context);
                            },
                          ),
                        ),
                      ],
                      material: (context, platform) =>
                          MaterialAlertDialogData(content: const TextField()),
                      cupertino: (context, platform) =>
                          CupertinoAlertDialogData(
                              content: const CupertinoTextField()),
                    );
                  });
            },
            cupertino: (context, platform) =>
                CupertinoIconButtonData(icon: const Icon(CupertinoIcons.add)),
            material: (context, platform) =>
                MaterialIconButtonData(icon: const Icon(Icons.add)),
          )
        ],
      ),
      body: BlocBuilder<NoteBloc, NoteState>(
        builder: (context, state) {
          if (state is Notes) {
            return Center(
                child: GridView.builder(
                    itemCount: state.noteList.length,
                    gridDelegate:
                        const SliverGridDelegateWithFixedCrossAxisCount(
                            crossAxisCount: 3),
                    itemBuilder: (context, index) {
                      final note = state.noteList[index];
                      print(state.noteList.length);
                      return Card(
                        child: ListTile(
                          title: Text(note.time.toString()),
                          subtitle: Text(note.message),
                        ),
                      );
                    }));
          } else {
            return Center(
              child: PlatformCircularProgressIndicator(),
            );
          }
        },
      ),
    );
  }
}

I tried everything chat gpt told me including the equatable Package but it only increased my stress levels even further. I expect to see individual card elements added to the gridview on the saved button tapped but it kept on showing only one card until hot-reloaded.


Solution

  • update your note_bloc :

    class NoteBloc extends Bloc<NoteEvent, NoteState> {
      NoteBloc() : super(const Notes([])) {
        final List<NoteModel> noteModel = [];
        on<SavedNote>((event, emit) async {
          noteModel.add(NoteModel(
              id: noteModel.length + 1, time: event.time, message: event.message));
          await Future.delayed(const Duration(seconds: 1));
          emit(Notes(noteModel.toList()));
        });
      }
    }
    

    here video link : enter link description here