### Install Dependencies Source: https://bloclibrary.dev/tutorials/flutter-counter Run flutter pub get to install all the dependencies listed in pubspec.yaml. ```bash flutter pub get ``` -------------------------------- ### Bloc.observer and Bloc.transformer setup (v8.1.0) Source: https://bloclibrary.dev/migration Example of the new approach in v8.1.0 using Bloc.observer and Bloc.transformer directly for configuration. ```dart void main() { Bloc.observer = CustomBlocObserver(); Bloc.transformer = customEventTransformer(); // ... } ``` -------------------------------- ### Install dependencies Source: https://bloclibrary.dev/tutorials/ngdart-counter Install all project dependencies after updating pubspec.yaml. ```bash dart pub get ``` -------------------------------- ### Install Dependencies Source: https://bloclibrary.dev/tutorials/flutter-infinite-list Run this command after updating pubspec.yaml to install all project dependencies. ```bash flutter pub get ``` -------------------------------- ### Install bloc_tools CLI Source: https://bloclibrary.dev/lint/installation Install the bloc command-line tools globally to use the bloc linter from your terminal. ```bash dart pub global activate bloc_tools ``` -------------------------------- ### Use Bloc Instances Source: https://bloclibrary.dev/lint-rules/prefer_bloc This example demonstrates the 'GOOD' pattern of using a Bloc instance. It shows the equivalent functionality to the Cubit example. ```dart import 'package:bloc/bloc.dart'; enum CounterEvent { increment }; class CounterBloc extends Bloc { CounterBloc() : super(0) { on((event, emit) => emit(state + 1)); } } ``` -------------------------------- ### View bloc lint help Source: https://bloclibrary.dev/lint/installation After installation, you can view the help information for the bloc lint command. ```bash $ bloc lint --help Lint Dart source code. Usage: bloc lint [arguments] -h, --help Print this usage information. Run "bloc help" to see global options. ``` -------------------------------- ### Main Entrypoint Setup Source: https://bloclibrary.dev/tutorials/flutter-weather Initializes the WeatherApp, BlocObserver, and HydratedStorage for state persistence. Ensure WidgetsFlutterBinding is initialized before calling other methods. ```dart import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_weather/app.dart'; import 'package:flutter_weather/weather_bloc_observer.dart'; import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:path_provider/path_provider.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); Bloc.observer = const WeatherBlocObserver(); HydratedBloc.storage = await HydratedStorage.build( storageDirectory: kIsWeb ? HydratedStorageDirectory.web : HydratedStorageDirectory((await getTemporaryDirectory()).path), ); runApp(const WeatherApp()); } ``` -------------------------------- ### Create Flutter Project Source: https://bloclibrary.dev/tutorials/flutter-counter Use the flutter create command to start a new Flutter project. ```bash flutter create flutter_counter ``` -------------------------------- ### Example API Response Source: https://bloclibrary.dev/tutorials/flutter-infinite-list This is an example of the JSON data returned by the placeholder API, representing a list of posts. ```json [ { "userId": 1, "id": 1, "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", "body": "quia et suscipit suscipit recusandae consequuntur expedita et cum reprehenderit molestiae ut ut quas totam nostrum rerum est autem sunt rem eveniet architecto" }, { "userId": 1, "id": 2, "title": "qui est esse", "body": "est rerum tempore vitae sequi sint nihil reprehenderit dolor beatae ea dolores neque fugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis qui aperiam non debitis possimus qui neque nisi nulla" } ] ``` -------------------------------- ### Setup Bloc Instance for Tests Source: https://bloclibrary.dev/testing Declare and initialize a Bloc instance within a setUp function to be used across multiple tests. ```dart void main() { group(CounterBloc, () { late CounterBloc counterBloc; setUp(() { counterBloc = CounterBloc(); }); }); } ``` -------------------------------- ### Main Application Setup Source: https://bloclibrary.dev/tutorials/flutter-infinite-list Sets up the main function, initializes the bloc observer, and runs the root application widget. Ensure SimpleBlocObserver is imported for logging bloc transitions and errors. ```dart import 'package:bloc/bloc.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_infinite_list/app.dart'; import 'package:flutter_infinite_list/simple_bloc_observer.dart'; void main() { Bloc.observer = const SimpleBlocObserver(); runApp(const App()); } ``` -------------------------------- ### Basic Cubit Usage Example Source: https://bloclibrary.dev/bloc-concepts Demonstrates creating a Cubit, accessing its state, triggering a state change, and closing the Cubit. ```dart void main() { final cubit = CounterCubit(); print(cubit.state); // 0 cubit.increment(); print(cubit.state); // 1 cubit.close(); } ``` -------------------------------- ### Bloc v7.2.0: on API Example Source: https://bloclibrary.dev/migration Example of using the new `on` API in Bloc v7.2.0 for handling events. ```dart abstract class CounterEvent {} class Increment extends CounterEvent {} class CounterBloc extends Bloc { CounterBloc() : super(0) { on((event, emit) => emit(state + 1)); } } ``` -------------------------------- ### BlocOverrides.runZoned example (v8.0.x) Source: https://bloclibrary.dev/migration Example of how BlocOverrides.runZoned was used in v8.0.x to configure bloc observers and event transformers. ```dart void main() { BlocOverrides.runZoned( () { // ... }, blocObserver: CustomBlocObserver(), eventTransformer: customEventTransformer(), ); } ``` -------------------------------- ### Install All Dependencies Recursively Source: https://bloclibrary.dev/tutorials/flutter-todos After updating `pubspec.yaml`, run this command to install all project dependencies, including those in sub-packages, recursively. ```bash very_good packages get --recursive ``` -------------------------------- ### Flutter App Setup with Bloc Source: https://bloclibrary.dev/tutorials/github-search This code sets up the main application widget, including repository and bloc providers, and configures the MaterialApp for navigation and theming. It demonstrates how to inject dependencies and initialize the bloc for the search form. ```dart import 'package:common_github_search/common_github_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_github_search/search_form.dart'; void main() => runApp(const App()); class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) { return RepositoryProvider( create: (_) => GithubRepository(), dispose: (repository) => repository.dispose(), child: MaterialApp( title: 'GitHub Search', home: Scaffold( appBar: AppBar(title: const Text('GitHub Search')), body: BlocProvider( create: (context) => GithubSearchBloc( githubRepository: context.read(), ), child: const SearchForm(), ), ), ), ); } } ``` -------------------------------- ### Bloc Transition Example Source: https://bloclibrary.dev/bloc-concepts Illustrates a Bloc transition, showing the current state, event, and next state. Provides detailed traceability for state changes. ```dart Transition { currentState: AuthenticationState.authenticated, event: LogoutRequested, nextState: AuthenticationState.unauthenticated } ``` -------------------------------- ### Authentication Repository Package Source: https://bloclibrary.dev/tutorials/flutter-login Example pubspec.yaml for the authentication_repository package. ```yaml name: authentication_repository description: Dart package which manages the authentication domain. publish_to: none environment: sdk: ^3.12.0 ``` -------------------------------- ### Instantiate CounterCubit with Different Initial States Source: https://bloclibrary.dev/bloc-concepts Demonstrates creating CounterCubit instances with distinct starting values. ```dart final cubitA = CounterCubit(0); // state starts at 0 final cubitB = CounterCubit(10); // state starts at 10 ``` -------------------------------- ### Install Bloc Command-Line Tools Source: https://bloclibrary.dev/lint Use this command to globally activate the bloc command-line tools, which include the lint command. ```dart dart pub global activate bloc_tools ``` -------------------------------- ### BlocObserver Implementation (v6.1.x) Source: https://bloclibrary.dev/migration Example of implementing BlocObserver in v6.1.x to observe Bloc and Cubit lifecycle events. ```dart class SimpleBlocObserver extends BlocObserver { @override void onCreate(Cubit cubit) {...} @override void onEvent(Bloc bloc, Object event) {...} @override void onChange(Cubit cubit, Object event) {...} @override void onTransition(Bloc bloc, Transition transition) {...} @override void onError(Cubit cubit, Object error, StackTrace stackTrace) {...} @override void onClose(Cubit cubit) {...} } ``` -------------------------------- ### HydratedBloc Storage API v8.x.x Source: https://bloclibrary.dev/migration Example of setting up HydratedBloc storage using HydratedBlocOverrides.runZoned in v8.x.x. ```dart Future main() async { final storage = await HydratedStorage.build( storageDirectory: kIsWeb ? HydratedStorage.webStorageDirectory : await getTemporaryDirectory(), ); HydratedBlocOverrides.runZoned( () => runApp(App()), storage: storage, ); } ``` -------------------------------- ### BlocObserver Implementation (v7.0.0) Source: https://bloclibrary.dev/migration Example of implementing BlocObserver in v7.0.0, utilizing BlocBase for onCreate, onChange, and onError. ```dart class SimpleBlocObserver extends BlocObserver { @override void onCreate(BlocBase bloc) {...} @override void onEvent(Bloc bloc, Object event) {...} @override void onChange(BlocBase bloc, Object? event) {...} @override void onTransition(Bloc bloc, Transition transition) {...} @override void onError(BlocBase bloc, Object error, StackTrace stackTrace) {...} @override void onClose(BlocBase bloc) {...} } ``` -------------------------------- ### WeatherRepository Unit Tests Setup Source: https://bloclibrary.dev/tutorials/flutter-weather Sets up the WeatherRepository with a mocked OpenMeteoApiClient for testing. Includes tests for the constructor and the getWeather method's interactions with the API client. ```dart void main() { group('WeatherRepository', () { late open_meteo_api.OpenMeteoApiClient weatherApiClient; late WeatherRepository weatherRepository; setUp(() { weatherApiClient = MockOpenMeteoApiClient(); weatherRepository = WeatherRepository( weatherApiClient: weatherApiClient, ); }); group('constructor', () { test('instantiates internal weather api client when not injected', () { expect(WeatherRepository(), isNotNull); }); }); group('getWeather', () { const city = 'chicago'; const latitude = 41.85003; const longitude = -87.65005; test('calls locationSearch with correct city', () async { try { await weatherRepository.getWeather(city); } catch (_) {} verify(() => weatherApiClient.locationSearch(city)).called(1); }); test('throws when locationSearch fails', () async { final exception = Exception('oops'); when(() => weatherApiClient.locationSearch(any())).thenThrow(exception); expect( () async => weatherRepository.getWeather(city), throwsA(exception), ); }); ``` -------------------------------- ### App Widget Setup with Repositories and Authentication BLoC Source: https://bloclibrary.dev/tutorials/flutter-login Provides AuthenticationRepository and UserRepository, and initializes the AuthenticationBloc. Set lazy to false to ensure immediate subscription to authentication status. ```dart import 'package:authentication_repository/authentication_repository.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_login/authentication/authentication.dart'; import 'package:flutter_login/home/home.dart'; import 'package:flutter_login/login/login.dart'; import 'package:flutter_login/splash/splash.dart'; import 'package:user_repository/user_repository.dart'; class App extends StatelessWidget { const App({super.key}); @override Widget build(BuildContext context) { return MultiRepositoryProvider( providers: [ RepositoryProvider( create: (_) => AuthenticationRepository(), dispose: (repository) => repository.dispose(), ), RepositoryProvider(create: (_) => UserRepository()), ], child: BlocProvider( lazy: false, create: (context) => AuthenticationBloc( authenticationRepository: context.read(), userRepository: context.read(), )..add(AuthenticationSubscriptionRequested()), child: const AppView(), ), ); } } ``` -------------------------------- ### Install Very Good CLI Source: https://bloclibrary.dev/tutorials/flutter-todos Install the very_good_cli globally using Dart's package manager. This tool is used for creating and managing Flutter projects. ```bash dart pub global activate very_good_cli ``` -------------------------------- ### WeatherApp Widget Setup Source: https://bloclibrary.dev/tutorials/flutter-weather Sets up the WeatherApp widget, providing WeatherRepository and WeatherCubit using RepositoryProvider and BlocProvider. Handles theme configuration based on weather conditions. ```dart import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_weather/weather/weather.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:weather_repository/weather_repository.dart' show WeatherRepository; class WeatherApp extends StatelessWidget { const WeatherApp({super.key}); @override Widget build(BuildContext context) { return RepositoryProvider( create: (_) => WeatherRepository(), dispose: (repository) => repository.dispose(), child: BlocProvider( create: (context) => WeatherCubit(context.read()), child: const WeatherAppView(), ), ); } } class WeatherAppView extends StatelessWidget { const WeatherAppView({super.key}); @override Widget build(BuildContext context) { final seedColor = context.select( (WeatherCubit cubit) => cubit.state.weather.toColor, ); return MaterialApp( theme: ThemeData( appBarTheme: const AppBarTheme( backgroundColor: Colors.transparent, elevation: 0, ), colorScheme: ColorScheme.fromSeed(seedColor: seedColor), textTheme: GoogleFonts.rajdhaniTextTheme(), ), home: const WeatherPage(), ); } } extension on Weather { Color get toColor { switch (condition) { case WeatherCondition.clear: return Colors.yellow; case WeatherCondition.snowy: return Colors.lightBlueAccent; case WeatherCondition.cloudy: return Colors.blueGrey; case WeatherCondition.rainy: return Colors.indigoAccent; case WeatherCondition.unknown: return Colors.cyan; } } } ``` -------------------------------- ### Linter Warning Output Example Source: https://bloclibrary.dev/lint/configuration This is an example of the output you might see when the `avoid_flutter_imports` rule is violated. It indicates the specific rule, the file and line number, and provides a hint and documentation link. ```text warning[avoid_flutter_imports]: Avoid importing Flutter within bloc instances. --> counter_cubit.dart:2 | | import 'package:flutter/material.dart'; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = hint: Blocs should be decoupled from Flutter. docs: https://bloclibrary.dev/lint-rules/avoid_flutter_imports 1 issue found Analyzed 1 file ``` -------------------------------- ### HydratedBloc Storage API v9.0.0 Source: https://bloclibrary.dev/migration Example of setting up HydratedBloc storage using the new HydratedBloc.storage API in v9.0.0. ```dart Future main() async { WidgetsFlutterBinding.ensureInitialized(); HydratedBloc.storage = await HydratedStorage.build( storageDirectory: kIsWeb ? HydratedStorage.webStorageDirectory : await getTemporaryDirectory(), ); runApp(App()); } ``` -------------------------------- ### Basic Bloc Usage Example Source: https://bloclibrary.dev/bloc-concepts Instantiate a Bloc, print its initial state, add an event to trigger a state change, and then print the new state. Ensure to await `Future.delayed(Duration.zero)` to allow event processing. ```dart Future main() async { final bloc = CounterBloc(); print(bloc.state); // 0 bloc.add(CounterIncrementPressed()); await Future.delayed(Duration.zero); print(bloc.state); // 1 await bloc.close(); } ``` -------------------------------- ### Create New AngularDart Project Source: https://bloclibrary.dev/tutorials/github-search Use stagehand to generate a new AngularDart web application. Ensure stagehand is installed globally first. ```bash dart pub global activate stagehand ``` ```bash stagehand web-angular ``` -------------------------------- ### Enable Linter Rules in analysis_options.yaml Source: https://bloclibrary.dev/lint/configuration Configure the bloc linter by adding a list of rules under the top-level `bloc` key in your `analysis_options.yaml` file. This example enables the `avoid_flutter_imports` rule. ```yaml bloc: rules: - avoid_flutter_imports ``` -------------------------------- ### Cubit Change Example Source: https://bloclibrary.dev/bloc-concepts Shows a Cubit change, detailing the current and next state. Lacks the event information present in Bloc transitions. ```dart Change { currentState: AuthenticationState.authenticated, nextState: AuthenticationState.unauthenticated } ``` -------------------------------- ### Good: Communicating with Bloc via add Method Source: https://bloclibrary.dev/lint-rules/avoid_public_bloc_methods This example shows the recommended approach where the Bloc instance does not expose public methods, and communication is handled exclusively through the `add` method. ```dart import 'package:bloc/bloc.dart'; enum CounterEvent { increment }; class CounterBloc extends Bloc { CounterBloc() : super(0) { on((event, emit) => emit(state + 1)); } } ``` -------------------------------- ### Bloc Reacting to Repository Stream Source: https://bloclibrary.dev/architecture An example of a Bloc that listens to a repository's stream and emits states based on the incoming data. ```dart class AppIdeaRankingBloc extends Bloc { AppIdeaRankingBloc({required AppIdeasRepository appIdeasRepo}) : _appIdeasRepo = appIdeasRepo, super(AppIdeaInitialRankingState()) { on((event, emit) async { // When we are told to start ranking app ideas, we will listen to the // stream of app ideas and emit a state for each one. await emit.forEach( _appIdeasRepo.productIdeas(), onData: (String idea) => AppIdeaRankingIdeaState(idea: idea), ); }); } final AppIdeasRepository _appIdeasRepo; } ``` -------------------------------- ### Simplified Initialization (v4.0.0) Source: https://bloclibrary.dev/migration In v4.0.0, manual calls to super.initialState ?? DefaultInitialState() were required for HydratedBloc initialization. This example shows the v4.0.0 setup. ```dart class CounterBloc extends HydratedBloc { @override int get initialState => super.initialState ?? 0; } ``` -------------------------------- ### Bloc Stream Subscription Example Source: https://bloclibrary.dev/bloc-concepts Subscribe to a Bloc's stream to listen for state changes in real-time. Remember to cancel the subscription when no longer needed and close the Bloc. ```dart Future main() async { final bloc = CounterBloc(); final subscription = bloc.stream.listen(print); // 1 bloc.add(CounterIncrementPressed()); await Future.delayed(Duration.zero); await subscription.cancel(); await bloc.close(); } ``` -------------------------------- ### Update pubspec.yaml Dependencies Source: https://bloclibrary.dev/tutorials/flutter-login Update the pubspec.yaml file to include necessary dependencies for authentication and bloc management. Run 'flutter pub get' to install them. ```yaml name: flutter_login description: A new Flutter project. version: 1.0.0+1 publish_to: none environment: sdk: ^3.12.0 dependencies: authentication_repository: path: packages/authentication_repository bloc: ^9.0.0 equatable: ^2.1.0-dev.0 flutter: sdk: flutter flutter_bloc: ^9.1.0 formz: ^0.8.0 user_repository: path: packages/user_repository dev_dependencies: bloc_lint: ^0.3.0 bloc_test: ^10.0.0 flutter_test: sdk: flutter mocktail: ^1.0.0 flutter: uses-material-design: true ``` -------------------------------- ### Bloc Error and Transition Logging Source: https://bloclibrary.dev/bloc-concepts This output shows an example of an exception being caught and logged by the Bloc library. It includes the stack trace of the error, the Bloc's current state, the event that triggered the error, and the next state. It also demonstrates the logging of Bloc transitions and changes. ```dart Exception: increment error! #0 new CounterBloc. (file:///main.dart:10:58) #1 Bloc.on..handleEvent (package:bloc/src/bloc.dart:229:26) #2 Bloc.on. (package:bloc/src/bloc.dart:238:9) #3 _MapStream._handleData (dart:async/stream_pipe.dart:213:31) #4 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13) #5 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10) #6 CastStreamSubscription._onData (dart:_internal/async_cast.dart:85:11) #7 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10) #8 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11) #9 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7) #10 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11) #11 _WhereStream._handleData (dart:async/stream_pipe.dart:195:12) #12 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13) #13 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10) #14 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11) #15 _DelayedData.perform (dart:async/stream_impl.dart:515:14) #16 _PendingEvents.handleNext (dart:async/stream_impl.dart:620:11) #17 _PendingEvents.schedule. (dart:async/stream_impl.dart:591:7) #18 _microtaskLoop (dart:async/schedule_microtask.dart:40:21) #19 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5) #20 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13) #21 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:185:5) CounterBloc Exception: increment error! #0 new CounterBloc. (file:///main.dart:10:58) #1 Bloc.on..handleEvent (package:bloc/src/bloc.dart:229:26) #2 Bloc.on. (package:bloc/src/bloc.dart:238:9) #3 _MapStream._handleData (dart:async/stream_pipe.dart:213:31) #4 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13) #5 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10) #6 CastStreamSubscription._onData (dart:_internal/async_cast.dart:85:11) #7 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10) #8 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11) #9 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7) #10 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11) #11 _WhereStream._handleData (dart:async/stream_pipe.dart:195:12) #12 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:153:13) #13 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10) #14 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11) #15 _DelayedData.perform (dart:async/stream_impl.dart:515:14) #16 _PendingEvents.handleNext (dart:async/stream_impl.dart:620:11) #17 _PendingEvents.schedule. (dart:async/stream_impl.dart:591:7) #18 _microtaskLoop (dart:async/schedule_microtask.dart:40:21) #19 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5) #20 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:118:13) #21 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:185:5) Transition { currentState: 0, event: Instance of 'CounterIncrementPressed', nextState: 1 } CounterBloc Transition { currentState: 0, event: Instance of 'CounterIncrementPressed', nextState: 1 } CounterBloc Change { currentState: 0, nextState: 1 } Change { currentState: 0, nextState: 1 } ``` -------------------------------- ### Bloc v7.1.0: mapEventToState Example Source: https://bloclibrary.dev/migration Example of using the deprecated `mapEventToState` API in Bloc v7.1.0. ```dart abstract class CounterEvent {} class Increment extends CounterEvent {} class CounterBloc extends Bloc { CounterBloc() : super(0); @override Stream mapEventToState(CounterEvent event) async* { if (event is Increment) { yield state + 1; } } } ``` -------------------------------- ### Flutter App Entry Point Source: https://bloclibrary.dev/tutorials/flutter-login Sets up the root widget for the Flutter application. ```dart import 'package:flutter/widgets.dart'; import 'package:flutter_login/app.dart'; void main() => runApp(const App()); ``` -------------------------------- ### Main Application Entry Point Source: https://bloclibrary.dev/tutorials/flutter-timer Sets up the main function to run the root App widget. This is the entry point for the Flutter application. ```dart import 'package:flutter/material.dart'; import 'package:flutter_timer/app.dart'; void main() => runApp(const App()); ``` -------------------------------- ### Get Weather Method Source: https://bloclibrary.dev/tutorials/flutter-weather Fetches weather data for a given latitude and longitude. Throws `WeatherRequestFailure` on HTTP errors or `WeatherNotFoundFailure` if weather data is missing. ```dart /// Fetches [Weather] for a given [latitude] and [longitude]. Future getWeather({ required double latitude, required double longitude, }) async { final weatherRequest = Uri.https(_baseUrlWeather, 'v1/forecast', { 'latitude': '$latitude', 'longitude': '$longitude', 'current_weather': 'true' }); final weatherResponse = await _httpClient.get(weatherRequest); if (weatherResponse.statusCode != 200) { throw WeatherRequestFailure(); } final bodyJson = jsonDecode(weatherResponse.body) as Map; if (!bodyJson.containsKey('current_weather')) { throw WeatherNotFoundFailure(); } final weatherJson = bodyJson['current_weather'] as Map; return Weather.fromJson(weatherJson); } ``` -------------------------------- ### Bloc v7.1.0: transformEvents Example Source: https://bloclibrary.dev/migration Example of using the deprecated `transformEvents` API in Bloc v7.1.0 with `debounceTime` and `flatMap`. ```dart @override Stream> transformEvents(events, transitionFn) { return events .debounceTime(const Duration(milliseconds: 300)) .flatMap(transitionFn); } ``` -------------------------------- ### Verify HTTP Request for Weather Data Source: https://bloclibrary.dev/tutorials/flutter-weather Verifies that the `getWeather` method makes the correct HTTP GET request to the Open-Meteo API with the specified latitude and longitude. ```dart test('makes correct http request', () async { final response = MockResponse(); when(() => response.statusCode).thenReturn(200); when(() => response.body).thenReturn('{}'); when(() => httpClient.get(any())).thenAnswer((_) async => response); try { await apiClient.getWeather(latitude: latitude, longitude: longitude); } catch (_) {} verify( () => httpClient.get( Uri.https('api.open-meteo.com', 'v1/forecast', { 'latitude': '$latitude', 'longitude': '$longitude', 'current_weather': 'true', }), ), ).called(1); }); ``` -------------------------------- ### Bloc v7.1.0: transformTransitions Example Source: https://bloclibrary.dev/migration Example of using the deprecated `transformTransitions` API in Bloc v7.1.0 to debounce state transitions. ```dart @override Stream> transformTransitions( Stream> transitions, ) { return transitions.debounceTime(const Duration(milliseconds: 42)); } ``` -------------------------------- ### Initialize Firebase and Authentication Repository in main.dart Source: https://bloclibrary.dev/tutorials/flutter-firebase-login This snippet shows the main entry point for a Flutter application, initializing Firebase, setting up a Bloc observer, and running the main App widget with an AuthenticationRepository. ```dart import 'package:authentication_repository/authentication_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_firebase_login/app/app.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); Bloc.observer = const AppBlocObserver(); await Firebase.initializeApp(); final authenticationRepository = AuthenticationRepository(); await authenticationRepository.user.first; runApp(App(authenticationRepository: authenticationRepository)); } ``` -------------------------------- ### App Entrypoint Source: https://bloclibrary.dev/tutorials/flutter-todos The main function initializes the Flutter binding, instantiates the local storage API, and calls the bootstrap function. ```dart import 'package:flutter/widgets.dart'; import 'package:flutter_todos/bootstrap.dart'; import 'package:local_storage_todos_api/local_storage_todos_api.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); final todosApi = LocalStorageTodosApi( plugin: await SharedPreferences.getInstance(), ); bootstrap(todosApi: todosApi); } ``` -------------------------------- ### Sign Up with Email and Password Source: https://bloclibrary.dev/tutorials/flutter-firebase-login Creates a new user account with the provided email and password. Throws a SignUpWithEmailAndPasswordFailure on error. ```dart Future signUp({required String email, required String password}) async { try { await _firebaseAuth.createUserWithEmailAndPassword( email: email, password: password, ); } on firebase_auth.FirebaseAuthException catch (e) { throw SignUpWithEmailAndPasswordFailure.fromCode(e.code); } catch (_) { throw const SignUpWithEmailAndPasswordFailure(); } } ``` -------------------------------- ### CounterBloc Implementation Source: https://bloclibrary.dev/testing This is the CounterBloc implementation used for testing examples. ```dart sealed class CounterEvent {} final class CounterIncrementPressed extends CounterEvent {} final class CounterDecrementPressed extends CounterEvent {} class CounterBloc extends Bloc { CounterBloc() : super(0) { on((event, emit) => emit(state + 1)); on((event, emit) => emit(state - 1)); } } ``` -------------------------------- ### Initialize CounterApp with BlocProvider Source: https://bloclibrary.dev/flutter-bloc-concepts Sets up the root of the Counter application, providing the CounterBloc using BlocProvider to the widget tree. ```dart void main() => runApp(CounterApp()); class CounterApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: BlocProvider( create: (_) => CounterBloc(), child: CounterPage(), ), ); } } ``` -------------------------------- ### Create Flutter Project Source: https://bloclibrary.dev/tutorials/flutter-timer Use the Flutter CLI to create a new Flutter project for the timer application. ```bash flutter create flutter_timer ``` -------------------------------- ### AngularDart App Component Setup Source: https://bloclibrary.dev/tutorials/ngdart-counter Sets up the root AngularDart component, 'my-app', to include the CounterPageComponent. ```dart import 'package:angular_counter/src/counter_page/counter_page_component.dart'; import 'package:ngdart/angular.dart'; /// Top level application component. @Component( selector: 'my-app', templateUrl: 'app_component.html', directives: [CounterPageComponent], ) class AppComponent {} ``` -------------------------------- ### Flutter Project Structure with Packages Source: https://bloclibrary.dev/tutorials/flutter-weather Illustrates the project structure including the newly created 'open_meteo_api' package. ```tree flutter_weather |-- lib/ |-- test/ |-- packages/ |-- open_meteo_api/ |-- lib/ |-- src/ |-- models/ |-- location.dart |-- weather.dart |-- test/ ``` -------------------------------- ### Create Project Directory Source: https://bloclibrary.dev/tutorials/github-search Creates a new directory for the GitHub Search application and its shared common library. ```bash mkdir -p github_search/common_github_search ``` -------------------------------- ### Get Current User Source: https://bloclibrary.dev/tutorials/flutter-firebase-login Retrieves the currently cached user. Defaults to User.empty if no user is found in the cache. ```dart User get currentUser { return _cache.read(key: userCacheKey) ?? User.empty; } ``` -------------------------------- ### TodosOverviewPage Widget Source: https://bloclibrary.dev/tutorials/flutter-todos Sets up the BlocProvider for TodosOverviewBloc and renders the TodosOverviewView. It initializes the bloc with the TodosRepository and requests the initial subscription to todos. ```dart import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_todos/edit_todo/view/edit_todo_page.dart'; import 'package:flutter_todos/l10n/l10n.dart'; import 'package:flutter_todos/todos_overview/todos_overview.dart'; import 'package:todos_repository/todos_repository.dart'; class TodosOverviewPage extends StatelessWidget { const TodosOverviewPage({super.key}); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => TodosOverviewBloc( todosRepository: context.read(), )..add(const TodosOverviewSubscriptionRequested()), child: const TodosOverviewView(), ); } } class TodosOverviewView extends StatelessWidget { const TodosOverviewView({super.key}); @override Widget build(BuildContext context) { final l10n = context.l10n; return Scaffold( appBar: AppBar( title: Text(l10n.todosOverviewAppBarTitle), actions: const [ TodosOverviewFilterButton(), TodosOverviewOptionsButton(), ], ), body: MultiBlocListener( listeners: [ BlocListener( listenWhen: (previous, current) => previous.status != current.status, listener: (context, state) { if (state.status == TodosOverviewStatus.failure) { ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar( SnackBar( content: Text(l10n.todosOverviewErrorSnackbarText), ), ); } }, ), BlocListener( listenWhen: (previous, current) => previous.lastDeletedTodo != current.lastDeletedTodo && current.lastDeletedTodo != null, listener: (context, state) { final deletedTodo = state.lastDeletedTodo!; final messenger = ScaffoldMessenger.of(context); messenger ..hideCurrentSnackBar() ..showSnackBar( SnackBar( content: Text( l10n.todosOverviewTodoDeletedSnackbarText( deletedTodo.title, ), ), action: SnackBarAction( label: l10n.todosOverviewUndoDeletionButtonText, onPressed: () { messenger.hideCurrentSnackBar(); context.read().add( const TodosOverviewUndoDeletionRequested(), ); }, ), ), ); }, ), ], child: BlocBuilder( builder: (context, state) { if (state.todos.isEmpty) { if (state.status == TodosOverviewStatus.loading) { return const Center(child: CupertinoActivityIndicator()); } else if (state.status != TodosOverviewStatus.success) { return const SizedBox(); } else { return Center( child: Text( l10n.todosOverviewEmptyText, style: Theme.of(context).textTheme.bodySmall, ), ); } } return CupertinoScrollbar( child: ListView.builder( itemCount: state.filteredTodos.length, itemBuilder: (_, index) { final todo = state.filteredTodos.elementAt(index); return TodoListTile( todo: todo, onToggleCompleted: (isCompleted) { context.read().add( TodosOverviewTodoCompletionToggled( todo: todo, isCompleted: isCompleted, ), ); }, onDismissed: (_){ context.read().add( TodosOverviewTodoDeleted(todo), ); }, onTap: () { Navigator.of(context).push( EditTodoPage.route(initialTodo: todo), ); }, ); }, ), ); }, ), ), ); } } ``` -------------------------------- ### Main Application Entry Point Source: https://bloclibrary.dev/flutter-bloc-concepts The main function to run the Flutter application, starting with the WeatherApp widget. ```dart import 'package:flutter/material.dart'; import 'package:flutter_weather/app.dart'; void main() => runApp(const WeatherApp()); ``` -------------------------------- ### HydratedStorage decoupled from BlocDelegate (v4.0.0) Source: https://bloclibrary.dev/migration In v4.0.0, BlocSupervisor.delegate was used to set the HydratedBlocDelegate. This example shows the v4.0.0 approach. ```dart BlocSupervisor.delegate = await HydratedBlocDelegate.build(); ``` -------------------------------- ### Create Flutter Project Source: https://bloclibrary.dev/tutorials/flutter-infinite-list Use this command to create a new Flutter project for the infinite list application. ```bash flutter create flutter_infinite_list ``` -------------------------------- ### Rename HydratedStorage and HydratedBlocStorage (v4.0.0) Source: https://bloclibrary.dev/migration In v4.0.0, the concrete default storage implementation was HydratedBlocStorage. This example shows its usage. ```dart class MyHydratedStorage implements HydratedStorage { ... } ``` -------------------------------- ### Create Flutter App with Very Good CLI Source: https://bloclibrary.dev/tutorials/flutter-todos Use the very_good_cli to create a new Flutter project for the todos app. This command initializes the project with a description. ```bash very_good create flutter_app flutter_todos --desc "An example todos app that showcases bloc state management patterns." ``` -------------------------------- ### Initialize BlocObserver in main.dart Source: https://bloclibrary.dev/tutorials/flutter-counter Replace the contents of lib/main.dart to initialize the CounterObserver and run the CounterApp widget. This sets up the application's entry point. ```dart import 'package:bloc/bloc.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_counter/app.dart'; import 'package:flutter_counter/counter_observer.dart'; void main() { Bloc.observer = const CounterObserver(); runApp(const CounterApp()); } ``` -------------------------------- ### Bloc for Business Logic Source: https://bloclibrary.dev/architecture Example of a Bloc component that handles events and emits states. It depends on a repository to fetch data. ```dart class BusinessLogicComponent extends Bloc { BusinessLogicComponent(this.repository) { on((event, emit) async { try { final data = await repository.getAllDataThatMeetsRequirements(); emit(Success(data)); } catch (error) { emit(Failure(error)); } }); } final Repository repository; } ``` -------------------------------- ### SignUpCubit Implementation Source: https://bloclibrary.dev/tutorials/flutter-firebase-login Manages the sign-up form state and interacts with the AuthenticationRepository to create new user accounts. It handles changes to email, password, and confirmed password fields, and submits the form for sign-up. ```dart import 'package:authentication_repository/authentication_repository.dart'; import 'package:bloc/bloc.dart'; import 'package:equatable/equatable.dart'; import 'package:form_inputs/form_inputs.dart'; import 'package:formz/formz.dart'; part 'sign_up_state.dart'; class SignUpCubit extends Cubit { SignUpCubit(this._authenticationRepository) : super(const SignUpState()); final AuthenticationRepository _authenticationRepository; void emailChanged(String email) => emit(state.withEmail(email)); void passwordChanged(String password) => emit(state.withPassword(password)); void confirmedPasswordChanged(String confirmedPassword) { emit(state.withConfirmedPassword(confirmedPassword)); } Future signUpFormSubmitted() async { if (!state.isValid) return; emit(state.withSubmissionInProgress()); try { await _authenticationRepository.signUp( email: state.email.value, password: state.password.value, ); emit(state.withSubmissionSuccess()); } on SignUpWithEmailAndPasswordFailure catch (e) { emit(state.withSubmissionFailure(e.message)); } catch (_) { emit(state.withSubmissionFailure()); } } } ``` -------------------------------- ### Example of Flutter Import in Cubit Source: https://bloclibrary.dev/lint This code demonstrates an accidental import of a Flutter dependency into a Cubit. The linter will flag this as an issue. ```dart import 'package:bloc/bloc.dart'; import 'packages:flutter/material.dart'; class CounterCubit extends Cubit { CounterCubit() : super(0); } ``` -------------------------------- ### Avoid Cubit Instances Source: https://bloclibrary.dev/lint-rules/prefer_bloc This example demonstrates the 'BAD' pattern of using a Cubit instance. Prefer Bloc instances for consistency. ```dart import 'package:bloc/bloc.dart'; class CounterCubit extends Cubit { CounterCubit() : super(0); void increment() => emit(state + 1); } ``` -------------------------------- ### Sign Up Form Widget Source: https://bloclibrary.dev/tutorials/flutter-firebase-login Renders the sign-up form in response to SignUpState. Listens for state changes to navigate on success or show errors on failure. Requires SignUpCubit for state management. ```dart import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_firebase_login/sign_up/sign_up.dart'; import 'package:formz/formz.dart'; class SignUpForm extends StatelessWidget { const SignUpForm({super.key}); @override Widget build(BuildContext context) { return BlocListener( listener: (context, state) { if (state.status.isSuccess) { Navigator.of(context).pop(); } else if (state.status.isFailure) { ScaffoldMessenger.of(context) ..hideCurrentSnackBar() ..showSnackBar( SnackBar(content: Text(state.errorMessage ?? 'Sign Up Failure')), ); } }, child: Align( alignment: const Alignment(0, -1 / 3), child: Column( mainAxisSize: MainAxisSize.min, children: [ _EmailInput(), const SizedBox(height: 8), _PasswordInput(), const SizedBox(height: 8), _ConfirmPasswordInput(), const SizedBox(height: 8), _SignUpButton(), ], ), ), ); } } class _EmailInput extends StatelessWidget { @override Widget build(BuildContext context) { final displayError = context.select( (SignUpCubit cubit) => cubit.state.email.displayError, ); return TextField( key: const Key('signUpForm_emailInput_textField'), onChanged: (email) => context.read().emailChanged(email), keyboardType: TextInputType.emailAddress, decoration: InputDecoration( labelText: 'email', helperText: '', errorText: displayError != null ? 'invalid email' : null, ), ); } } class _PasswordInput extends StatelessWidget { @override Widget build(BuildContext context) { final displayError = context.select( (SignUpCubit cubit) => cubit.state.password.displayError, ); return TextField( key: const Key('signUpForm_passwordInput_textField'), onChanged: (password) => context.read().passwordChanged(password), obscureText: true, decoration: InputDecoration( labelText: 'password', helperText: '', errorText: displayError != null ? 'invalid password' : null, ), ); } } class _ConfirmPasswordInput extends StatelessWidget { @override Widget build(BuildContext context) { final displayError = context.select( (SignUpCubit cubit) => cubit.state.confirmedPassword.displayError, ); return TextField( key: const Key('signUpForm_confirmedPasswordInput_textField'), onChanged: (confirmPassword) => context.read().confirmedPasswordChanged(confirmPassword), obscureText: true, decoration: InputDecoration( labelText: 'confirm password', helperText: '', errorText: displayError != null ? 'passwords do not match' : null, ), ); } } class _SignUpButton extends StatelessWidget { @override Widget build(BuildContext context) { final isInProgress = context.select( (SignUpCubit cubit) => cubit.state.status.isInProgress, ); if (isInProgress) return const CircularProgressIndicator(); final isValid = context.select( (SignUpCubit cubit) => cubit.state.isValid, ); return ElevatedButton( key: const Key('signUpForm_continue_raisedButton'), style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), ), backgroundColor: Colors.orangeAccent, ), onPressed: isValid ? () => context.read().signUpFormSubmitted() : null, child: const Text('SIGN UP'), ); } } ``` -------------------------------- ### Sign Up Page Widget Source: https://bloclibrary.dev/tutorials/flutter-firebase-login Defines the SignUpPage widget, responsible for creating and providing the SignUpCubit. It includes routing and UI setup. ```dart import 'package:authentication_repository/authentication_repository.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_firebase_login/sign_up/sign_up.dart'; class SignUpPage extends StatelessWidget { const SignUpPage({super.key}); static Route route() { return MaterialPageRoute(builder: (_) => const SignUpPage()); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Sign Up')), body: Padding( padding: const EdgeInsets.all(8), child: BlocProvider( create: (_) => SignUpCubit(context.read()), child: const SignUpForm(), ), ), ); } } ``` -------------------------------- ### Enable prefer_build_context_extensions Rule (YAML List) Source: https://bloclibrary.dev/lint-rules/prefer_build_context_extensions Configuration snippet for `analysis_options.yaml` to enable the `prefer_build_context_extensions` lint rule using a list format. ```yaml bloc: rules: - prefer_build_context_extensions ``` -------------------------------- ### Add Angular Bloc to AngularDart Project Source: https://bloclibrary.dev/getting-started Install the angular_bloc package for AngularDart projects using the dart pub add command. ```bash dart pub add angular_bloc ``` -------------------------------- ### Interact with Cubit and Observe Changes Source: https://bloclibrary.dev/bloc-concepts Demonstrates how to instantiate a Cubit, trigger a state change, and observe the output in the console. ```dart void main() { CounterCubit() ..increment() ..close(); } ``` -------------------------------- ### Add Flutter Bloc to Flutter Project Source: https://bloclibrary.dev/getting-started Install the flutter_bloc package for Flutter projects using the flutter pub add command. ```bash flutter pub add flutter_bloc ``` -------------------------------- ### Add Bloc to Dart Project Source: https://bloclibrary.dev/getting-started Install the core Bloc package for Dart projects using the dart pub add command. ```bash dart pub add bloc ```