0

I have a bloc called specialityBloc which will fetch doctors according to their speciality from firestore by delegating it to a repository.

The problem is when I want to fetch different doctors with different speciality and emit them from same state(fetchSuccessState).

I am able to fetch them separately from firestore but when It comes to rendering in the UI using different bloc builders(that listen to the same specialityBloc).It overrides the old data(which was there in the first Api call) and replaces it with the result of the subsequent api calls.

I want to keep the old the in the state and render it UI and also render the new Data below it(which was emitted from the same state).

Here is my Specialitybloc

  SpecialityBloc() : super(InitialState()){
    on<GetSpeciality>((event, emit) async {
      emit(WaitingSpeciality());
      try{
        final data = await FirebaseRepo.getDoctorsBySpeciality(event.speciality);
        data.fold((l){
          emit(GetSpecialitySuccess(doctors:l));
        }, (r){
          
        });
      }catch(e){
        print(e);
      }
    });
  }
  
}

abstract class SpecialityState extends Equatable {

}

abstract class SpecialityEvent {

}

class InitialState extends SpecialityState {
@override
  List<Object> get props => [];
}

class WaitingSpeciality extends SpecialityState {
  @override
  List<Object> get props => [];

}

class GetSpecialitySuccess extends SpecialityState {
final List<DoctorModel> doctors;
GetSpecialitySuccess({required this.doctors});
@override
  List<Object> get props => [doctors];
}

class GetSpeciality extends SpecialityEvent {

  final String speciality;
  GetSpeciality(this.speciality);

}```

This is the UI part

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:patient_app/ui/screens/home/home_bloc/popular_bloc.dart';
import 'package:patient_app/ui/screens/home/home_bloc/speciality_bloc.dart';
import 'package:patient_app/ui/widgets/gridViewLoading.dart';
import 'package:shimmer/shimmer.dart';
import 'package:patient_app/ui/screens/home/home_bloc/home_bloc.dart';
import 'package:patient_app/ui/widgets/custom_carousel.dart';
import 'package:patient_app/ui/widgets/search_bar.dart';
import 'package:patient_app/ui/widgets/square.dart';
import 'package:patient_app/ui/widgets/username.dart';

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

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

class _HomeState extends State<Home> {

  @override
  void initState() {
    super.initState();

    context.read<HomeBloc>().add(GetUserInfo());
    context.read<PopularBloc>().add(GetPopularDoctors());
    context.read<SpecialityBloc>().add(GetSpeciality('paediatrics'));
    context.read<SpecialityBloc>().add(GetSpeciality('gynaecologist'));
  }

  @override
  Widget build(BuildContext context) {
    return   SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.only(left:20.0,right: 20,),
            child: Column(

              children: [
                const SizedBox(height: 35,),
                BlocBuilder<HomeBloc,HomeState>(
                  
                  builder: (ctx,state){
                    if(state is Waiting){
                      return Align(
                        alignment: Alignment.centerLeft,
                        child: Shimmer.fromColors(
                          baseColor: Colors.amber,
                          highlightColor: Colors.grey[300]!,
                          child: Container(
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(10),
                              color: Colors.amber,
                            ),
                            height: 20,width: 150,),
                        ));
                    }
                    if(state is Success){
                      return UserName(name: state.data.name!);
                    }
                    else{
                      return Container();
                    }
                    
                  },
                ),
                CustomCarousel(slides: [
                  SizedBox(
                    width: double.infinity,
                    child: Image.network("https://cdn.pixabay.com/photo/2020/09/13/20/24/doctor-5569298_960_720.png",fit: BoxFit.cover,),
                  ),
                  SizedBox(
                    width: double.infinity,
                    child: Image.network("https://cdn.pixabay.com/photo/2021/11/20/03/16/doctor-6810750_960_720.png",fit: BoxFit.cover,),
                  ),
                ]),
                const SearchBar(),
                
                BlocBuilder<PopularBloc,PopularState>(builder: (ctx,state){
                  if(state is WaitingPopular){
                    return const GridViewLoading();
                  }
                  if(state is PopularDoctorsSuccess){
                   
                    return Square(doctors: state.doctors,title: "Popular Doctors",);
                  }
                  return Container();
                }),
               
                
                BlocBuilder<SpecialityBloc,SpecialityState>(builder: (ctx,state){

                  if(state is WaitingSpeciality){
                    return const GridViewLoading();
                  }
                  if(state is GetSpecialitySuccess){
                    return Square(doctors: state.doctors,title: " Paediatrics",);
                  }
                  return Container();

                }),

                BlocBuilder<SpecialityBloc,SpecialityState>(builder: (ctx,state){

                  if(state is WaitingSpeciality){
                    return const GridViewLoading();
                  }
                  if(state is GetSpecialitySuccess){
                    return Square(doctors: state.doctors,title: "Gynaecologist",);
                  }
                  return Container();

                })
                
              ],
            ),
          ),
        );
  }
}


BestOFBest
  • 43
  • 7

2 Answers2

0

if I got you correctly you are trying to save the old result that you got from the API to use it later on right ? if so then : you can try to make you var a global variable and then when the data comes you can assign the data you got in this variable to use it later on in another state like that

late final data;
//or the other way you can make data as a list here
//of the type object you are using ex Doctor or so..



SpecialityBloc() : super(InitialState()){
    on<GetSpeciality>((event, emit) async {
      emit(WaitingSpeciality());
      try{
        data = await FirebaseRepo.getDoctorsBySpeciality(event.speciality);
        data.fold((l){
          emit(GetSpecialitySuccess(doctors:l));
        }, (r){
          
        });
      }catch(e){
        print(e);
      }
    });
  }
// now you can use your data variable that has the info with any other state or with whatever you want 

and just add them to your list each time and then you can get back to whatever object you want from the list like maybe search for an a doctor using some ID and if it's not in the list you can fetch it and add it again to the list and here you can use the same state to render a different object, also try to remove the equatable from your code and try without it if you don't really need it.

Baraa Aljabban
  • 992
  • 13
  • 22
0

If I am getting it right, the simplest and the right approach would be to have different events returning different states for each specialty, while acting on the same or different builders on the UI; based on buildWhen method of the bloc builder. Internally you can write a reusable method which does the API query, trigger it each time with a different event (specialty) and it can emit a respective state based on the method caller.

Benefits: better control on the UI and better testability.

atketan
  • 169
  • 5
  • This seems legit but it won't be dynamic because if i have 100 speciality then following your approach I would have 100 events which is not feasible I think in long term. – BestOFBest Apr 07 '22 at 02:52
  • In that case, you can probably explore the option of having an enum, which you can pass with each Event/State as an identifier. So, every event would have a Specialty attached to it and every State would have a Specialty and response data mapped with it. This way you can have same state returning different set of data for each specialty. – atketan Apr 07 '22 at 06:40
  • Can you show me an example of this?. Thanks by the way. – BestOFBest Apr 07 '22 at 08:07