Home > Enterprise >  My BlocBuilder is not changing state when I Emit and Event, I'm using get_it to inject dependen
My BlocBuilder is not changing state when I Emit and Event, I'm using get_it to inject dependen

Time:07-12

Here is my BlocProvider

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

import 'package:movies_app_leal/core/routes/routes.dart';
import 'package:movies_app_leal/features/auth/presentation/bloc/blocs.dart';
import 'package:movies_app_leal/injection_dependecy_container.dart' as di;

void main() async {
  SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
      statusBarColor: Colors.transparent,
      statusBarIconBrightness: Brightness.light,
      systemNavigationBarIconBrightness: Brightness.light)); // status bar color

  WidgetsFlutterBinding
      .ensureInitialized(); // It is important to add this, to ensure not to have problems with Futures initialized the injection container
  await di.init(); // Initialize the dependency injection container

  runApp(
    MultiBlocProvider(
      providers: [
        BlocProvider(
          create: (_) => di.sl<AuthBloc>(),
        )
      ],
      child: const MyApp(),
    ),
  );
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      routes: routes,
      theme: ThemeData.dark().copyWith(
        textTheme: ThemeData.dark().textTheme.apply(
              fontFamily: 'Gilroy',
            ),
      ),
      initialRoute: RoutesPages.loading.name,
    );
  }
}

Here is my BlocBuilder

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

import 'package:movies_app_leal/features/auth/presentation/bloc/auth_bloc/auth_bloc.dart';
import 'package:movies_app_leal/features/auth/presentation/pages/welcome_page.dart';
import 'package:movies_app_leal/features/tv_show/presentation/pages/home_page.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocBuilder<AuthBloc, AuthState>(
        builder: (context, state) {
          switch (state.runtimeType) {
            case AuthInitialState:
              return const WelcomePage();
            case AuthLoadingState:
              return const _LoadingIndicator();
            case AuthLoadedState:
              return const HomePage();
            case AuthErrorState:
              return const WelcomePage();
            default:
              return const WelcomePage();
          }
        },
      ),
    );
  }
}

class _LoadingIndicator extends StatelessWidget {
  const _LoadingIndicator({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: MediaQuery.of(context).size.height,
      width: MediaQuery.of(context).size.width,
      child: const CircularProgressIndicator(),
    );
  }
}

Here is my injection container file

import 'package:get_it/get_it.dart';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';

import 'package:movies_app_leal/core/util/failure_to_message.dart';
import 'package:movies_app_leal/core/util/url_path_converter.dart';
import 'package:movies_app_leal/features/auth/data/datasources/auth_local_data_source.dart';
import 'package:movies_app_leal/features/auth/data/datasources/auth_remote_data_source.dart';
import 'package:movies_app_leal/features/auth/data/repositories/auth_repository_impl.dart';
import 'package:movies_app_leal/features/auth/domain/repositories/auth_repository.dart';
import 'package:movies_app_leal/features/auth/domain/usecases/log_out.dart';
import 'package:movies_app_leal/features/auth/domain/usecases/login.dart';
import 'package:movies_app_leal/features/auth/presentation/bloc/auth_bloc/auth_bloc.dart';

final sl = GetIt.instance;

Future<void> init() async {
  //! Features - Auth
  //? Bloc
  sl.registerFactory(() => AuthBloc(login: sl(), logout: sl(), message: sl()));

  //? UseCases
  sl.registerLazySingleton(() => Login(sl()));
  sl.registerLazySingleton(() => LogOut(sl()));

  //? Repository
  sl.registerLazySingleton<AuthRepository>(
      () => AuthRepositoryImpl(localDataSource: sl(), remoteDataSource: sl()));

  //? Data Sources
  sl.registerLazySingleton<AuthRemoteDataSource>(() => AuthRemoteDataSourceImpl());
  sl.registerLazySingleton<AuthLocalDataSource>(
      () => AuthLocalDataSourceImpl(sharedPreferences: sl()));

  //! Core
  sl.registerLazySingleton(() => UrlPathConverter());
  sl.registerLazySingleton(() => Message());

  //! External
  final sharedPreferences = await SharedPreferences.getInstance();
  sl.registerLazySingleton(() => sharedPreferences);
  sl.registerLazySingleton(() => http.Client());
}

Here I handle my event

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

import 'package:movies_app_leal/core/routes/routes.dart';
import 'package:movies_app_leal/core/theme/theme_data.dart';
import 'package:movies_app_leal/core/widgets/movies_action_button.dart';
import 'package:movies_app_leal/core/widgets/movies_button.dart';
import 'package:movies_app_leal/core/widgets/movies_text_field.dart';
import 'package:movies_app_leal/core/widgets/movies_title.dart';
import 'package:movies_app_leal/features/auth/data/models/auth_model.dart';
import 'package:movies_app_leal/features/auth/presentation/bloc/blocs.dart';
import 'package:movies_app_leal/features/auth/presentation/widgets/backgroud_container.dart';

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

  @override
  Widget build(BuildContext context) {
    final topPadding = MediaQuery.of(context).padding.top;
    final authProvider = BlocProvider.of<AuthBloc>(context);

    return Scaffold(
      body: BackgroundContainer(
        child: Container(
          padding: EdgeInsets.only(top: topPadding),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const MoviesTitle(text: "Welcome!", fontSize: 25, centered: true),
              _LoginForm(
                authProvider: authProvider,
              )
            ],
          ),
        ),
      ),
    );
  }
}

class _LoginForm extends StatelessWidget {
  final AuthBloc authProvider;

  const _LoginForm({
    Key? key,
    required this.authProvider,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final TextEditingController nameController = TextEditingController();
    final TextEditingController passwordController = TextEditingController();

    void _onLogin() {
      final authData = AuthModel(name: nameController.text, password: passwordController.text);
      authProvider.add(AuthLoginEvent(auth: authData));
    }

    void _onClose() {
      Navigator.pushReplacementNamed(context, RoutesPages.welcome.name);
    }

    return SingleChildScrollView(
      child: Container(
        padding: const EdgeInsets.all(20),
        decoration: BoxDecoration(
          color: black.withOpacity(0.9),
          borderRadius: const BorderRadius.only(
            topLeft: Radius.circular(40),
            topRight: Radius.circular(40),
          ),
        ),
        child: Column(
          children: [
            MoviesActionButton(
              function: _onClose,
              icon: Icons.close_rounded,
              iconColor: grey,
              splasColor: yellow,
            ),
            MoviesTextField(controller: nameController, hintText: "Name"),
            MoviesTextField(
              controller: passwordController,
              hintText: "Password",
              obscureText: true,
            ),
            const SizedBox(height: 80),
            MoviesButton(
              text: "Log in",
              onPressed: _onLogin,
              normalButton: true,
            ),
            const SizedBox(height: 50),
          ],
        ),
      ),
    );
  }
}

And this is my Bloc

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';

import 'package:movies_app_leal/core/usecases/usecase.dart';
import 'package:movies_app_leal/core/util/failure_to_message.dart';
import 'package:movies_app_leal/features/auth/domain/entities/auth.dart';
import 'package:movies_app_leal/features/auth/domain/usecases/log_out.dart';
import 'package:movies_app_leal/features/auth/domain/usecases/login.dart';

part 'auth_event.dart';
part 'auth_state.dart';

class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final Login login;
  final LogOut logout;
  final Message message;

  AuthBloc({required this.login, required this.logout, required this.message})
      : super(AuthInitialState()) {
    on<AuthLoginEvent>(_onLogIn);
    on<AuthLogoutEvent>(_onLogOut);
  }

  /// Handle the user log in.
  void _onLogIn(AuthLoginEvent event, Emitter<AuthState> emit) async {
    emit(AuthLoadingState()); // Show the loading state.
    final failureOrAuth = await login(Params(event.auth));

    failureOrAuth.fold(
        (failure) => emit(AuthErrorState(message: message.mapFailureToMessage(failure))),
        (authData) => emit(AuthLoadedState(auth: authData)));
  }

  /// Handle the user log out.
  void _onLogOut(AuthLogoutEvent event, Emitter<AuthState> emit) async {
    emit(AuthLoadingState()); // Show the loading state.
    final failureOrAuth = await logout(NoParams());

    failureOrAuth.fold(
        (failure) => emit(AuthErrorState(message: message.mapFailureToMessage(failure))),
        (_) => emit(AuthInitialState()));
  }
}

I don't know why my BloBuilder is not changing the Widget ??? I'm trying to change between screen using the Bloc events and making some process in the background using Clean Architecture, but I don't understand why is this happening.

CodePudding user response:

You can't pass down the Bloc instance. Because it refers to current widget's context. try creating own AuthBloc instance inside _LoginForm.

CodePudding user response:

Instead of

sl.registerFactory(() => AuthBloc(login: sl(), logout: sl(), message: sl()));

try using

sl.registerLazySingleton(() => AuthBloc(login: sl(), logout: sl(), message: sl()));

and try to use Bloc using

var authBloc = sl<AuthBloc>();
  • Related