Bloc: How to use two states in one UI?

Created on 28 Jun 2020  路  3Comments  路  Source: felangel/bloc

Hello, I have project where I need to build different parts of one screen according to 2 states here is what I did:

my Home screen:

`
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: BlocBuilder(
builder: (BuildContext context, state) {
return SingleChildScrollView(
child: Container(
decoration: new BoxDecoration(color: Color(0xfffafafa)),
child: Column(
children: [
if (state is SliderLoaded) ...{
CarouselSlider(
items: state.response
.map((url) => HomeSlider(url: url))
.toList(),
options: CarouselOptions(
scrollDirection: Axis.horizontal,
autoPlay: true,
height: MediaQuery.of(context).size.height * 0.29,
),
),
} else if (state is SliderLoading) ...{
Container(
height: 30,
width: 30,
child: CircularProgressIndicator(),
)
} else if (state is SliderLoadFailure)
Center(child: Text(state.error)),
BlocBuilder(
builder: (context,state){
if(state is CategoryLoaded){
categoriesForHome=state.categoryResponse.categories.skip(5).take(2);
}
return Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.only(
// top: MediaQuery.of(context).size.height * 0.00009,
left: MediaQuery.of(context).size.width * 0.04,
right: MediaQuery.of(context).size.width * 0.04,
),

                child:  Flex(
                  direction: Axis.horizontal,
                  children: [
                    // if(state is CategoryLoaded)
                    Expanded(
                      child: Stack(
                        children: <Widget>[
                          Opacity(
                            opacity: 0.15000000596046448,
                            child: Container(
                              height: 318.h,
                            ),
                          ),
                          Positioned.fill(
                            child: Container(
                              child: Image(
                                image: AssetImage(
                                    'assets/images/top_cat2/topcat2.png'),
                              ),
                            ),
                          ),
                          Positioned(
                              top: 175.0.h,
                              left: 56.0.w,
                              child: Column(
                                children: [
                                  Text(categoriesForHome!=null?categoriesForHome.first.name: "兀胤賱丕賱鬲賰 丕賱噩丿賷丿丞 賱賱丿賵丕賲",
                                      style: TextStyle(
                                        fontFamily: 'HelveticaNeueLTArabic',
                                        color: Color(0xffffffff),
                                        fontSize: 14,
                                        fontWeight: FontWeight.w700,
                                        fontStyle: FontStyle.normal,
                                      )),
                                  SizedBox(
                                    height: 8.0.h,
                                  ),
                                  Container(
                                    alignment: Alignment.center,
                                    margin: EdgeInsets.only(left: 140.w),
                                    width: 118.w,
                                    height: 40.h,
                                    decoration: new BoxDecoration(
                                        color: Color(0xffffffff)),
                                    child: new Text("鬲爻賵賯賶 丕賱兀賳",
                                        style: TextStyle(
                                          fontFamily: 'HelveticaNeueLTArabic',
                                          color: Color(0xff000000),
                                          fontSize: 15.ssp,
                                          fontWeight: FontWeight.w700,
                                          fontStyle: FontStyle.normal,
                                        )),
                                  )
                                ],
                              ))
                        ],
                      ),
                    ),  
                }
            ),
          ],
        ),
      ),
    );
  }),

`

and here is my category bloc:

`class CategoryBloc extends Bloc {
final categoryRepository=CategoryRepository();
@override
CategoryState get initialState => CategoryInitial();

@override
Stream mapEventToState(
CategoryEvent event,
) async* {
if(event is GetCategories){
yield CategoryLoading();
final categoryResponse=await categoryRepository.categories();
yield CategoryLoaded(categoryResponse);
}
}
}`

and here is my home bloc:

`class HomeBloc extends Bloc {
HomeRepository _homeRepository;
HomeBloc(){
_homeRepository=HomeRepository();
}
@override
HomeState get initialState => HomeInitial();

@override
Stream mapEventToState(
HomeEvent event,
) async* {
print('hello from there!');
if(event is GetSlider){
yield SliderLoading();
try{
final response=await _homeRepository.getSlider();
print(response.toString());
yield SliderLoaded(response);
CategoryBloc().add(GetCategories());//after slider call the categories //first time I did this event dispatch from multibloc provi
//but didn't work any advice?
}catch(error){
print(error.toString());
yield SliderLoadFailure(error.toString());
CategoryBloc().add(GetCategories());//after slider call the categories

}
}
}
}
`

here is myApp:

class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: MultiBlocProvider( providers: [ BlocProvider<HomeBloc>( lazy: false, create: (context) => HomeBloc()..add(GetSlider()), ), BlocProvider<CategoryBloc>( lazy: false, create: (context) => CategoryBloc()//..add(GetCategories()), //here tried to fire 2 events together but gave no result? ), ], //IntroBloc()..add(GetDefaultLanguage()),//RegisterBloc() , child: HomeScreen(), //IntroScreen()//SignInScreen(), ), ); } }

Now the slider response is coming to the UI but the categories when yield doesn't exposed in the UI
I need solution for this please?

question

Most helpful comment

Thanks I used nested blocBuilder as in my code now and added the 2 events at app widget before didn't work but later worked.

All 3 comments

@felangel please have look this?

Hi @EngAddow 馃憢
Thanks for opening an issue!

If you need to react to two separate states in your UI you can nest BlocBuilders like:

@override
Widget build(BuildContext context) {
  return BlocBuilder<BlocA, StateA>(
    builder: (context, stateA) {
      return BlocBuilder<BlocB, StateB>(
        builder: (context, stateB) {
          // do something here based on stateA and stateB
        },
      );
    },
  );
}

Another option is to refactor your two blocs into a single bloc if they are not needed individually.
A third option is to create a third bloc which subscribes to the first two blocs and aggregates the states into a single state.

Hope that helps 馃憤

If you're still having trouble please share a link to a github repo which reproduces the issue you're facing, thanks 馃檹

Thanks I used nested blocBuilder as in my code now and added the 2 events at app widget before didn't work but later worked.

Was this page helpful?
0 / 5 - 0 ratings