Search code examples
flutterblocflutter-bloc

BlocBuilder only build once and stop rebuild with subsequent emit


I have an IconButton that click on it will pin/unpin the window, and the icon will change according to pinned or not. The first click on the button will trigger a rebuild event, but subsequent click does not. And I have absolutely no idea on it.

I created a minimal example here: https://gist.github.com/TENX-S/7a811cb23b3b0ed220b75f4b2cda7fd3, for repo: https://github.com/TENX-S/miniexample

I tried to read documentation on https://bloclibrary.dev/, but I'm not getting the answer to it.

enter image description here


Solution

    • The problem is the implementation of SettingsCubit

    • Link to the output

    • Below is my updated version of your settings.dart

    @JsonSerializable()
    class Settings {
    
      final bool alwaysOnTop;
    
      Settings({required this.alwaysOnTop});
    
      const Settings._({
        this.alwaysOnTop = false,
      });
    
      const Settings.initial() : this._();
    
      const Settings.update(bool onTop): this._(alwaysOnTop: onTop);
    
      factory Settings.fromJson(Map<String, dynamic> json) => _$SettingsFromJson(json);
    
      Map<String, dynamic> toJson() => _$SettingsToJson(this);
    
    }
    
    class SettingsCubit extends HydratedCubit<Settings> {
      SettingsCubit() : super(const Settings.initial());
    
      set alwaysOnTop(bool pinned) => emit(Settings.update(pinned));
    
      bool get alwaysOnTop => state.alwaysOnTop;
    
      @override
      Settings? fromJson(Map<String, dynamic> json) {
        return Settings.fromJson(json);
      }
    
      @override
      Map<String, dynamic>? toJson(Settings state) {
        return state.toJson();
      }
    }
    
    
    • your HomePage build method
    @override
      Widget build(BuildContext context) {
        final settingsCubit = context.read<SettingsCubit>();
        return Scaffold(
          body: Center(
            child: IconButton(
              icon: settingsCubit.alwaysOnTop ? const Icon(FluentIcons.pin_24_filled): const Icon(FluentIcons.pin_24_regular),
              onPressed: () {
                settingsCubit.alwaysOnTop = !widget.pinned;
              },
            ),
          ),
        );
      }