Bloc: BlocBuilder Doesn't update widget after state changed

Created on 25 Apr 2020  路  2Comments  路  Source: felangel/bloc

I'm trying to change app theme using bloc implementation. But, when the state changed, builder doesnt recall.

Here is my theme_event.dart

part of 'theme_bloc.dart';

abstract class ThemeEvent extends Equatable {
  // Passing class fields in a list to the Equatable super class
  ThemeEvent([List props = const <dynamic>[]]);

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

class ThemeChanged extends ThemeEvent {
  final AppTheme theme;

  ThemeChanged({
    @required this.theme,
  }) : super([theme]);
}

theme_state.dart

```part of 'theme_bloc.dart';

class ThemeState extends Equatable {
final ThemeData themeData;

ThemeState({
@required this.themeData,
});

@override
List get props => [];
}


### theme_bloc.dart
```import 'dart:async';

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:musica_tl/helper/theme_helper.dart';

part 'theme_event.dart';
part 'theme_state.dart';

class ThemeBloc extends Bloc<ThemeEvent, ThemeState> {
  @override
  ThemeState get initialState =>
      ThemeState(themeData: ThemeHelper.appThemeData[AppTheme.BlueDark]);

  @override
  Stream<ThemeState> mapEventToState(ThemeEvent event) async* {
    if (event is ThemeChanged) {  
      yield ThemeState(themeData: ThemeHelper.appThemeData[event.theme]);
    }
  }
}

theme_helper value:

```enum AppTheme {
GreenLight,
GreenDark,
BlueLight,
BlueDark,
}

class ThemeHelper {
static final appThemeData = {
AppTheme.GreenLight: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.green,
),
AppTheme.GreenDark: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.green[700],
),
AppTheme.BlueLight: ThemeData(
brightness: Brightness.light,
primaryColor: Colors.blue,
),
AppTheme.BlueDark: ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.blue[700],
),
};
}

### main.dart:
```import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:musica_tl/screens/onboarding/onboarding_screen.dart';
import 'app/bloc/theme/bloc/theme_bloc.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => ThemeBloc(),
      child: BlocBuilder<ThemeBloc, ThemeState>(
        builder: _buildWithTheme,
      ),
    );
  }

  Widget _buildWithTheme(BuildContext context, ThemeState state) {
    return MaterialApp(
      title: 'Musica.tl',
      home: OnBoardingScreen(),
      theme: state.themeData,
    );
  }
}

and this is how change the state using event:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:musica_tl/app/bloc/theme/bloc/theme_bloc.dart';
import 'package:musica_tl/helper/theme_helper.dart';

class OnBoardingScreen extends StatelessWidget {
 const OnBoardingScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('OnBoarding'),
      ),
      body: ListView.builder(
        padding: EdgeInsets.all(8),
        itemCount: AppTheme.values.length,
        itemBuilder: (context, index) {
          // Enums expose their values as a list - perfect for ListView
          // Store the theme for the current ListView item
          final itemAppTheme = AppTheme.values[index];
          return Card(
            // Style the cards with the to-be-selected theme colors
            color: ThemeHelper.appThemeData[itemAppTheme].primaryColor,
            child: ListTile(
              title: Text(
                itemAppTheme.toString(),
                // To show light text with the dark variants...
                style: ThemeHelper.appThemeData[itemAppTheme].textTheme.body1,
              ),
              onTap: () {
                // This will make the Bloc output a new ThemeState,
                // which will rebuild the UI because of the BlocBuilder in main.dart
                BlocProvider.of<ThemeBloc>(context).add(ThemeChanged(theme: itemAppTheme));
              },
            ),
          );
        },
      ),
    );
  }
}

I've checked if the state has changed but i have no idea why the blocBuilder doesnt recall and update the view.

question waiting for response

Most helpful comment

Ah I see, now the problem solved and worked well!.

it happened because I dont know about the new syntax (prefer to use props instead of super).
In theme_state I forgot to pass the variable to the props, it should be like this:

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

instead of

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

Before, I was trying to implement super in the constructor to pass the variable and its give me error like this:

Too many positional arguments: 0 expected, but 1 found.
Try removing the extra arguments.dart(extra_positional_arguments)

Thank you 馃憤

All 2 comments

Hi @ariefwijaya 馃憢
Thanks for opening an issue!

It looks like you鈥檙e not using Equatable properly which is likely causing this issue. Please make sure to override props in your state class and pass the ThemeData into the props override. I highly recommend checking out the faqs for more details.

Hope that helps 馃憤

If you鈥檙e still having trouble can you please share a link to a sample app which illustrates the issue? Thanks!

Ah I see, now the problem solved and worked well!.

it happened because I dont know about the new syntax (prefer to use props instead of super).
In theme_state I forgot to pass the variable to the props, it should be like this:

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

instead of

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

Before, I was trying to implement super in the constructor to pass the variable and its give me error like this:

Too many positional arguments: 0 expected, but 1 found.
Try removing the extra arguments.dart(extra_positional_arguments)

Thank you 馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

krusek picture krusek  路  3Comments

wheel1992 picture wheel1992  路  3Comments

MahdiPishguy picture MahdiPishguy  路  3Comments

1AlexFix1 picture 1AlexFix1  路  3Comments

shawnchan2014 picture shawnchan2014  路  3Comments