Search code examples
flutterblocstate-managementcubit

Pass Data Between to Bloc Cubit


Hi everybody i have 2 cubit the first is get A List of Object and represent into a list View the sconed cubit is get the details of the item when click it from the list and it take a id as parameter to put it into the dio function as id of the item but i face a problem

here is the route class

class Routes {
  static const String initialRout = '/';
  static const String episodeRoute = '/episode';
  static const String callUsRoute = '/callUse';
  static const String whoWeAreRoute = '/whoWeAre';
  static const String programInfo = '/programInfo';
}

class AppRoutes {
  static Route<dynamic>? onGenerateRoute(RouteSettings routeSettings) {
    switch (routeSettings.name) {
      case Routes.initialRout:
        return MaterialPageRoute(
            builder: ((context) => MultiBlocProvider(
                  providers: [
                    BlocProvider<RandomQuoteCubit>(
                      create: (context) => di.sl<RandomQuoteCubit>(),
                    ),
                    BlocProvider<ShowEpisodeCubit>(
                      create: (context) => di.sl<ShowEpisodeCubit>(),
                    ),
                    BlocProvider<GetLastEpisodsCubit>(
                      create: (context) => di.sl<GetLastEpisodsCubit>(),
                    ),
                    BlocProvider<AudioNewsCubit>(
                      create: (context) => di.sl<AudioNewsCubit>(),
                    ),
                  ],
                  child: const QutoScreen(),
                )));
      case Routes.episodeRoute:
        return MaterialPageRoute(
            builder: ((context) => BlocProvider<ShowEpisodeCubit>(
                  create: (_) => di.sl<ShowEpisodeCubit>(),
                  child: const EpisodeScreen(),
                )));
      case Routes.callUsRoute:
        return MaterialPageRoute(builder: ((context) => const CallUs()));
      case Routes.whoWeAreRoute:
        return MaterialPageRoute(builder: ((context) => const WhoUs()));
      case Routes.programInfo:
        return MaterialPageRoute(builder: ((context) => ProgramInfoWidget()));
      default:
        return undefinedRoute();
    }
  }

  static Route<dynamic> undefinedRoute() {
    return MaterialPageRoute(
        builder: (context) => const Scaffold(
              body: Center(
                child: Text('No Route Found'),
              ),
            ));
  }
}
GetIt sl = GetIt.instance;

Future<void> init() async {
  //? Features
  // Blocs
  sl.registerFactory<RandomQuoteCubit>(
      () => RandomQuoteCubit(getRandomQuoteUseCase: sl()));

  sl.registerFactory<GetLastEpisodsCubit>(
      () => GetLastEpisodsCubit(getLastEpisods: sl()));

  sl.registerFactory<AudioNewsCubit>(
      () => AudioNewsCubit(getNewsLettersUseCase: sl()));

  GetIt.instance.registerFactory<ShowEpisodeCubit>(
      () => ShowEpisodeCubit(getEpisodeInfoUseCase: sl()));

  // Use Cases
  sl.registerLazySingleton(() => GetRandomQuote(quoteRepository: sl()));
  sl.registerLazySingleton(() => GetLastEpisods(lastEpisodesRepo: sl()));
  sl.registerLazySingleton(() => GetNewsLetters(newsLettersRepo: sl()));
  GetIt.instance.registerLazySingleton(
      () => GetEpisodeInfoUseCase(episodeRepository: sl()));

  // Repository
  GetIt.instance.registerLazySingleton<QuoteRepository>(() =>
      QuoteRepositoryImpl(
          networkInfo: sl(),
          randomQuoteRemoteDataSource: sl(),
          randomQuoteLocalDataSource: sl()));

  GetIt.instance.registerLazySingleton<LastEpisodsRepository>(() =>
      LastEpisodesImpl(
          localDataSource: sl(), networkInfo: sl(), remoteDataSource: sl()));

  GetIt.instance.registerLazySingleton<NewsLettersRepository>(() =>
      NewsLettersImpl(
          localDataSource: sl(), networkInfo: sl(), remoteDataSource: sl()));

  GetIt.instance.registerLazySingleton<EpisodeRepository>(() =>
      EpisodeInfoRepositoryImpl(
          episodeInfoLocalDataSource: sl(),
          episodeInfoRemoteDataSource: sl(),
          networkInfo: sl()));

  // Data Sources
  sl.registerLazySingleton<RandomQuoteLocalDataSource>(
      () => RandomQuotLocalDataSourceImpl(sharedPreferences: sl()));
  sl.registerLazySingleton<RandomQuoteRemoteDataSource>(
      () => RandomQuoteRemoteDataSourceImpl(apiConsumer: sl()));

  sl.registerLazySingleton<LastEpisodesLocalDataSource>(
    () => LastEpiosdesLocalDataSourecImpl(sharedPreferences: sl()),
  );
  sl.registerLazySingleton<LastEpisodesRemoteDataSource>(
      () => LastEpisodesRemoteDataSourceImpl(apiConsumer: sl()));

  sl.registerLazySingleton<NewsLetterLocalDataSource>(
    () => NewsLetterLocalDataSourecImpl(sharedPreferences: sl()),
  );
  sl.registerLazySingleton<NewsLettersRemoteDataSource>(
      () => NewsLettersRemoteDataSourceImpl(apiConsumer: sl()));

  sl.registerLazySingleton<EpisodeInfoLocalDataSource>(
    () => EpisodeInfoLocalDataSourceImpl(sharedPreferences: sl()),
  );
  sl.registerLazySingleton<EpisodeInfoRemoteDataSource>(
      () => EpisodeInfoRemoteDataSourceImpl(apiConsumer: sl()));
}

here is the lastEpisede Cubit list

// ignore: depend_on_referenced_packages
import 'package:bloc/bloc.dart';
import 'package:clean_code_templete/core/error/failure.dart';
import 'package:clean_code_templete/core/use_cases/use_cases.dart';
import 'package:clean_code_templete/features/get_last_episods/domain/entities/lastepisods.dart';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';

import '../../../../core/utils/app_strings.dart';
import '../../domain/usecases/get_last_episods.dart';

part 'get_last_episods_state.dart';

class GetLastEpisodsCubit extends Cubit<GetLastEpisodsState> {
  final GetLastEpisods getLastEpisods;

  GetLastEpisodsCubit({required this.getLastEpisods})
      : super(GetLastEpisodsInitial());

  Future<void> getLastEpiosdes() async {
    emit(GetLastEpisodsIsLoading());
    Either<Failure, LastEpisodsEnitiy>? response =
        await getLastEpisods(NoParams());
    emit(response.fold(
        (failure) => GetLastEpisodsIsError(msg: _mapFailureToMsg(failure)),
        (lastepisodes) =>
            GetLastEpisodsIsLoaded(lastEpisodsEnitiy: lastepisodes)));
  }

  String _mapFailureToMsg(Failure failure) {
    switch (failure.runtimeType) {
      case ServerFailure:
        return AppStrings.serverFailure;
      case CacheFailure:
        return AppStrings.cacheFailure;
      default:
        return AppStrings.unexpecredError;
    }
  }
}

here is the lastEpisod Widget that i put the data and Ui inside it

class LastEpiosdesContent extends StatelessWidget {
  final LastEpisodsEnitiy lastEpisodsEnitiy;
  final Function(int?) onIdSelected;

  const LastEpiosdesContent({
    Key? key,
    required this.lastEpisodsEnitiy,
    required this.onIdSelected,
  }) : super(key: key);
  // هان راح يكون الشغل تبع نقل الاي دي

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      // ignore: prefer_const_constructors
      GeneralHeaders(
        text: 'آخر الحلقات',
        icon: CustomIcon.mediamodifier_design_black_fire,
      ),
      SizedBox(
        height: 200,
        width: double.infinity,
        child: ListView.builder(
          scrollDirection: Axis.horizontal,
          itemCount: lastEpisodsEnitiy.list!.length,
          itemBuilder: (context, index) {
            return InkWell(
              onTap: () async {
                onIdSelected(lastEpisodsEnitiy.list![index].id);
              },
              child: Container(
                margin: const EdgeInsets.all(5),
                height: 180,
                width: 300,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment
                      .spaceAround, // adjust the alignment as needed
                  children: [
                    Flexible(
                      child: SizedBox(
                        height: 150, // adjust the height as needed
                        child: Stack(
                          children: [
                            ClipRRect(
                              borderRadius:
                                  const BorderRadius.all(Radius.circular(10)),
                              child: Stack(
                                children: [
                                  Image.network(
                                    '${lastEpisodsEnitiy.list![index].img}',
                                    width: 300,
                                    height: 200,
                                    fit: BoxFit.fill,
                                  ),
                                  Padding(
                                    padding: const EdgeInsets.only(
                                        right: 10, left: 10, bottom: 10),
                                    child: Align(
                                      alignment: Alignment.bottomCenter,
                                      child: Container(
                                        decoration: BoxDecoration(boxShadow: [
                                          BoxShadow(
                                            color:
                                                Colors.black.withOpacity(0.9),
                                            spreadRadius: 15,
                                            blurRadius: 25,
                                            offset: const Offset(0, 15),
                                          ),
                                        ]),
                                        child: Directionality(
                                          textDirection: TextDirection.ltr,
                                          child: Row(
                                            mainAxisAlignment:
                                                MainAxisAlignment.spaceBetween,
                                            children: [
                                              Text(
                                                '20/02/2023',
                                                style: Theme.of(context)
                                                    .textTheme
                                                    .titleSmall,
                                              ),
                                              Text(
                                                'على بصيرة',
                                                style: Theme.of(context)
                                                    .textTheme
                                                    .titleSmall,
                                              ),
                                            ],
                                          ),
                                        ),
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                    Padding(
                      padding:
                          const EdgeInsets.only(left: 10, top: 5, right: 10),
                      child: Align(
                        alignment: Alignment.centerRight,
                        child: Text(
                          '${lastEpisodsEnitiy.list![index].name}',
                          style: Theme.of(context).textTheme.displayMedium,
                          textDirection: TextDirection.rtl,
                          textAlign: TextAlign.start,
                          maxLines: 1,
                          overflow: TextOverflow.ellipsis,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            );
          },
        ),
      ),

    ]);
  }
}

here is the screen that i mange the state of the cubit and take the id and pass it to the show episode cubit

import 'package:clean_code_templete/features/get_last_episods/presentation/cubit/get_last_episods_cubit.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';

import '../../../../config/routes/app_routes.dart';
import '../../../../core/utils/app_colors.dart';
import '../../../../core/widgets/error.dart';
import '../../../show_episode/presentation/cubit/show_episode_cubit.dart';
import '../widgets/last_episodes_content.dart';

class LastEpisodesScreen extends StatefulWidget {
  const LastEpisodesScreen({super.key});

  @override
  State<LastEpisodesScreen> createState() => _LastEpisodesScreenState();
}

class _LastEpisodesScreenState extends State<LastEpisodesScreen> {
  _getLastEpisodes() =>
      BlocProvider.of<GetLastEpisodsCubit>(context).getLastEpiosdes();

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

  Widget _buildBodyContent() {
    return BlocBuilder<GetLastEpisodsCubit, GetLastEpisodsState>(
        builder: ((context, state) {
      if (state is GetLastEpisodsIsLoading) {
        return Center(
          child: SpinKitFadingCircle(
            color: AppColors.mainColor,
          ),
        );
      } else if (state is GetLastEpisodsIsError) {
        return ErrorScreen(
          onPress: () {
            _getLastEpisodes();
          },
        );
      } else if (state is GetLastEpisodsIsLoaded) {
        return Column(
          children: [
            LastEpiosdesContent(
              lastEpisodsEnitiy: state.lastEpisodsEnitiy,
              onIdSelected: (id) async {
                BlocProvider.of<ShowEpisodeCubit>(context)
                    .getEpisodeDetiles(id: id);
                await Navigator.of(context).pushNamed(
                  Routes.episodeRoute,
                );
              },
            ),
          ],
        );
      } else {
        return Center(
          child: SpinKitFadingCircle(
            color: AppColors.mainColor,
          ),
        );
      }
    }));
  }

  @override
  Widget build(BuildContext context) {
    return RefreshIndicator(
      onRefresh: () async {
        _buildBodyContent();
      },
      child: Scaffold(
        body: _buildBodyContent(),
      ),
    );
  }
}

here is the showEpisode Cubit

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';

import '../../../../core/utils/app_colors.dart';
import '../../../../core/widgets/error.dart';
import '../cubit/show_episode_cubit.dart';
import '../widgets/episode_widget.dart';

class EpisodeScreen extends StatefulWidget {
  const EpisodeScreen({super.key});

  @override
  State<EpisodeScreen> createState() => _EpisodeScreenState();
}

class _EpisodeScreenState extends State<EpisodeScreen> {
  _getEpisodeInfo() =>
      BlocProvider.of<ShowEpisodeCubit>(context).getEpisodeDetiles(id: 22570);

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

  Widget _buildBodyContent() {
    return BlocBuilder<ShowEpisodeCubit, ShowEpisodeState>(
        builder: ((context, state) {
      if (state is ShowEpisodeIsLoading) {
        return Center(
          child: SpinKitFadingCircle(
            color: AppColors.mainColor,
          ),
        );
      } else if (state is ShowEpisodeIsError) {
        return ErrorScreen(
          onPress: () {
            _getEpisodeInfo();
          },
        );
      } else if (state is ShowEpisodelsLoaded) {
        return EpisodeWidget(
          episodeEnitiy: state.episodeEnitiy,
          image:
              'https://www.pixelstalk.net/wp-content/uploads/2016/06/HD-Country-Image.jpg',
        );
      } else {
        return Center(
          child: SpinKitFadingCircle(
            color: AppColors.mainColor,
          ),
        );
      }
    }));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(body: _buildBodyContent());
  }
}

here is the error that I face it when click the item

E/flutter (10566): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception:         BlocProvider.of() called with a context that does not contain a ShowEpisodeCubit.
E/flutter (10566):         No ancestor could be found starting from the context that was passed to BlocProvider.of<ShowEpisodeCubit>().
E/flutter (10566):
E/flutter (10566):         This can happen if the context you used comes from a widget above the BlocProvider.
E/flutter (10566):
E/flutter (10566):         The context used was: BlocBuilder<GetLastEpisodsCubit, GetLastEpisodsState>(dependencies: [_InheritedProviderScope<GetLastEpisodsCubit?>], state: _BlocBuilderBaseState<GetLastEpisodsCubit, GetLastEpisodsState>#8e584)
E/flutter (10566):
E/flutter (10566): #0      BlocProvider.of
bloc_provider.dart:99
E/flutter (10566): #1      _LastEpisodesScreenState._buildBodyContent.<anonymous closure>.<anonymous closure>
last_episods_screen.dart:50
E/flutter (10566): #2      LastEpiosdesContent.build.<anonymous closure>.<anonymous closure>
last_episodes_content.dart:34
E/flutter (10566): #3      _InkResponseState.handleTap
ink_well.dart:1096
E/flutter (10566): #4      GestureRecognizer.invokeCallback
recognizer.dart:253
E/flutter (10566): #5      TapGestureRecognizer.handleTapUp
tap.dart:627```

finally thank you very much for your 

I have 2 cubit the first is get A List of Object and represent into a list View 
the sconed cubit is get the details of the item when click it from the list and it take a id as parameter to 
put it into the dio function as id of the item but i face a problem 

Solution

  • I edit the route class as shown below and it works.

    enter image description here

    Routes {
      static const String initialRout = '/';
      static const String episodeRoute = '/episode';
      static const String callUsRoute = '/callUse';
      static const String whoWeAreRoute = '/whoWeAre';
      static const String programInfo = '/programInfo';
    }
    class AppRoutes {
      static Route<dynamic>? onGenerateRoute(RouteSettings routeSettings) {
        switch (routeSettings.name) {
          case Routes.initialRout:
            return MaterialPageRoute(
                builder: ((context) => MultiBlocProvider(
                      providers: [
                        BlocProvider<RandomQuoteCubit>(create: (context) => di.sl<RandomQuoteCubit>()),
                        BlocProvider<GetLastEpisodsCubit>(create: (context) => di.sl<GetLastEpisodsCubit>()),
                        BlocProvider<ShowEpisodeCubit>(create: (context) => di.sl<ShowEpisodeCubit>()),
                        BlocProvider<AudioNewsCubit>(create: (context) => di.sl<AudioNewsCubit>()),
                        BlocProvider<ProgramInfoCubit>( create: (context) => di.sl<ProgramInfoCubit>()),
                      ],
                      child: MaterialApp(
                        debugShowCheckedModeBanner: false,
                        theme: appTheme(),
                        initialRoute: Routes.initialRout,
                        routes: {
                          Routes.initialRout: (context) => const QutoScreen(),
                          Routes.episodeRoute: (context) => const EpisodeScreen(),
                          Routes.callUsRoute: (context) => const CallUs(),
                          Routes.whoWeAreRoute: (context) => const WhoUs(),
                          Routes.programInfo: (context) =>const ProgramInfoScreen(),
                        },
                      ),
                    )));
          default:
            return undefinedRoute();
        }
      }
    
      static Route<dynamic> undefinedRoute() {
        return MaterialPageRoute(
            builder: (context) => const Scaffold(
                  body: Center(
                    child: Text('No Route Found'),
                  ),
                ));
      }
    }