Giter Club home page Giter Club logo

blocfromzerotohero's Introduction

The Best & Most Complete Flutter BLoc Course - https://youtu.be/THCkkQ-V1-8

Why is that you may ask? I'll give you a couple of reasons:

  • Every topic is structured nicely on chapters and subchapters, and everyone of these are available on the YouTube timeline for easier "jump-to-topic" access.

  • Whenever you're not sure about a topic/implementation, after you covered the entire course, you can just jump right into the topic using YouTube timeline, just like a cheatsheet of bloc.

  • Nice animations for understanding and learning practices, real code for putting everything you learned to practice.

  • The Course is based on my BLoC - From Zero to Hero popular playlist, but obviously it's not just a merged version of all the videos. I have modified each and everyone of them to keep only the best of the best!

  • Many more you'll find by browsing out a couple of minutes into the course to see if it's right for you!

Before you check it out though, I would like to tell you that this series is designed with both the theoretical and most importantly, practical (coding) parts of every discussed topic. All of the project files can be found on my github page.

Also, the series was carefully monitored by the amazing creator of bloc_library, Felix Angelov, known on GitHub as @Felangel

A briefing of everything that's been covered in this playlist, so you know what to expect:

#1 - Why BLoC? In this video I explained why I chose bloc_library for both the state management solution and the architectural structure of my apps

#2 - BLoC Core Concepts - In this tutorial I got really in-depth in explaining streams, and the concepts of blocs & cubits.

#3 - Flutter BLoc Concepts - Here, I discussed each and every single one of bloc_library's concept like BlocProvider, BlocBuilder, BlocListener and many many more. These concepts are obviously explained and tested in every tutorial, since they are the base of bloc_library.

#4 - BLoC Architecture - In this tutorial I made a short introduction on what I believe it's the best architecture to follow in order to structure and scale your code over time! This video has no code inside my github page, since I'm planning on using it extensively on my follow-up tutorial series on building real world apps!

#5 - BLoC Testing - Testing is one of the most important pillars of programming, oftenly omitted by developers. In this video I'll explain what are the basics of testing a bloc-built small application.

#6 - BLoC Access & Navigation - In this tutorial I got really in-depth on what are the routing options on which you can successfully provide a cubit/bloc to the widget tree.

#7 - Bloc-to-bloc Communication - Here I wanted all my viewers to understand how important it is to know how to make 2 blocs/cubit communicate one with another.

#8 - BuildContext In-Depth - This tutorial is not really related to the bloc_library, but since build contexts are used everywhere inside a flutter app, I realised that most of people didn't understand how they really work. This video is also useful as it spreads out the knowledge gained from tutorial number 3 and 6.

#9 - Bloc 6.1.0 - During my tutorial series, a new version of bloc_library got released, containing some important changes like context.watch, context.read and context.select. All of these are covered in this video, as always, with intuitive examples.

#10 - Bloc State not Updating - In this video, I explained why most of the new developers encounter this popular issue of a state of a bloc/cubit not updating.

#11 - Maintaining State with Hydrated_Bloc - In this tutorial I got really in-depth about how you can store the state of multiple blocs/cubits on the app's internal storage on your device. This is a key concept in developing a successful Flutter app, having bloc_library as the state management feature.

#12 - Debugging Blocs/Cubits, Naming Conventions and other tips and tricks is the last video of this series, covering other important topics found inside the flutter_bloc library.

blocfromzerotohero's People

Contributors

raychencode avatar thewckd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

blocfromzerotohero's Issues

Questions about Bloc Provider using Route access method

Hi WCKD,
I use route access method to locally provide bloc just like how you do in the youtube tutorial. However the situation is a bit weird. The thing is that after exception the program does not shutdown and the widget depending on the bloc(DatesBloc) seems to work correctly, which means it finds the bloc and give the correct responses to the widget just causing exception earlier. What's more, if I provide the bloc in homepage wrapping DatesPage instead of providing it by route, the exception is just gone. And, if I exchange the order of DatesPage and ChatsPage in HomePage, it turns out to be that it is ChatsBloc causes the exception instead of DatesBloc. Is there any possible reason to this phenomenon or any possible solution to resolve this issue?
截圖 2021-03-26 下午12 58 40
截圖 2021-03-26 下午1 07 33

截圖 2021-03-26 下午1 00 26
截圖 2021-03-26 下午1 01 07

[Part 5] Running the test fails with null safety enabled

I am trying to run the code with null safety enabled in the project. I keep getting the following error when I run the test on counter_cubit_test.dart:

Null check operator used on a null value

This is the code in the counter_cubit.dart file:

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

part 'counter_state.dart';

class CounterCubit extends Cubit<CounterState> {
  CounterCubit() : super(CounterState(counterValue: 0));

  void increment() => emit(
      CounterState(counterValue: state.counterValue! + 1, wasIncremented: true));

  void decrement() => emit(CounterState(
      counterValue: state.counterValue! - 1, wasIncremented: false));
}

This is the code in the counter_state.dart file:

part of 'counter_cubit.dart';

class CounterState extends Equatable {
  final int? counterValue;
  final bool? wasIncremented;

  CounterState({required this.counterValue, this.wasIncremented});

  @override
  List<Object> get props => [this.counterValue!, this.wasIncremented!];
}

This is the code in the main.dart file:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_counter_bloc/cubits/counter_cubit.dart';

void main() => runApp(MyApp());

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      theme: ThemeData(
        primaryColor: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: BlocProvider<CounterCubit>(
        create: (context) => CounterCubit(),
        child: MyHomePage(title: "Flutter Demo Home Page"),
      ),
    );
  }
}

///Used a stateless widget since state is handled by the Bloc library in this case. I referred the
///following link: https://stackoverflow.com/questions/58864869/flutter-state-management-bloc-stateless-vs-stateful-widget
class MyHomePage extends StatelessWidget {
  final String? title;

  const MyHomePage({Key? key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title!),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("You have pushed this button this many times:"),
            BlocConsumer<CounterCubit, CounterState>(
              ///Refactored the if...else block into a function to show the SnackBar Widget
                listener: (context, state) => snackBarFunction(state.wasIncremented!, context),
                ///Refactored the if...else block into a function that returns a Text widget
                builder: (context, state) => counterText(state.counterValue!, context)),
            SizedBox(height: 24),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                FloatingActionButton(
                  onPressed: () => BlocProvider.of<CounterCubit>(context).decrement(),
                  heroTag: Text("$title"),
                  tooltip: "Decrement",
                  child: Icon(Icons.remove),
                ),
                FloatingActionButton(
                  onPressed: () => BlocProvider.of<CounterCubit>(context).increment(),
                  heroTag: Text("$title #2"),
                  tooltip: "Increment",
                  child: Icon(Icons.add),
                ),
              ],
            )
          ],
        ),
      ),
    );
  }
}

///This function is used to show the snack bar widget depending on whether the counter was incremented
///or decremented
void snackBarFunction(bool counterState, context) {
  if (counterState == true) {
    ///Scaffold.of(context).showSnackBar(snackBar) is deprecated
    ///Using ScaffoldMessenger.of(context).showSnackBar(snackBar) instead
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text("Incremented!"),
      duration: Duration(milliseconds: 300),
    ));
  } else {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text("Decremented!"),
      duration: Duration(milliseconds: 300),
    ));
  }
}

///This function is used to change the returned Text widget in accordance with the value of the counter
Text counterText(int counterValue, context) {
  if (counterValue < 0) {
    return Text("BRR, Negative $counterValue",
        style: Theme.of(context).textTheme.headline4);
  } else if (counterValue % 2 == 0) {
    return Text("YAAAY $counterValue",
        style: Theme.of(context).textTheme.headline4);
  } else if (counterValue == 5) {
    return Text("HMM, NUMBER 5", style: Theme.of(context).textTheme.headline4);
  } else {
    return Text("$counterValue",
        style: Theme.of(context).textTheme.headline4);
  }
}

This is the code in the counter_cubit_test.dart file:

import 'package:flutter_counter_bloc/cubits/counter_cubit.dart';
import 'package:test/test.dart';
import 'package:bloc_test/bloc_test.dart';

void main() {
  group("CounterCubit", (){

    CounterCubit? counterCubit;

    setUp((){
      counterCubit = CounterCubit();
    });
    tearDown((){
      counterCubit!.close();
    });

    test("Initial state of CounterCubit is CounterState(counterValue: 0)", () {
      expect(counterCubit!.state, CounterState(counterValue: 0));
    });

    blocTest<CounterCubit, CounterState>(
      'the CounterCubit should emit a CounterState(counterValue:1, wasIncremented:true) when the increment function is called',
      build: () => counterCubit!,
      act: (cubit) => cubit.increment(),
      expect: () => <CounterState>[CounterState(counterValue: 1, wasIncremented: true)],
    );

    blocTest<CounterCubit, CounterState>(
      'the CounterCubit should emit a CounterState(counterValue:-1, wasIncremented:false) when the decrement function is called',
      build: () => counterCubit!,
      act: (cubit) => cubit.decrement(),
      expect: () => <CounterState>[CounterState(counterValue: -1, wasIncremented: false)],
    );
  });
}

Local BLoc access actually works.

I am following your tutorial and for some reason when I am just pushing the second screen , it does not crash and works as intended. I am using bloc 8.1 and Flutter 3.10. Has there been an update that now supports Flutter anonymous routes or now the two pages share a context?

Trying to run the chapter 2 code gives error

Improperly formatted define flag: Blocs

FAILURE: Build failed with an exception.

  • Where:
    Script '/Users/a35850/development/flutter/packages/flutter_tools/gradle/flutter.gradle' line: 1035

  • What went wrong:
    Execution failed for task ':app:compileFlutterBuildDebug'.

Process 'command '/Users/a35850/development/flutter/bin/flutter'' finished with non-zero exit value 1

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

  • Get more help at https://help.gradle.org

BUILD FAILED in 1s
Exception: Gradle task assembleDebug failed with exit code 1

[Part 3]

image

CounterState({@required this.counterValue, this.wasIncremented});

this shows an error and it works fine when i remove '@' from required, it also asks to add required to 'this.wasIncremented' .
means CounterState({required this.counterValue, required this.wasIncremented}); works fine ,
but in counter_cubit it asks to pass the required parameter of 'this.wasIncremented' in countercubit()

CHAPTER 5.1 BLoC Testing Implementation (1:19:00 - 1:21:00)

@flutterly, awesome course so far but i seem to be stuck at (1:21:00) my error is

The argument type 'List' can't be assigned to the parameter type 'dynamic Function()'. [29,17]
The argument type 'List' can't be assigned to the parameter type 'dynamic Function()'. [35,17]
so i went on to run the test and it FAILED... :'(

please could you or someone facing the same error/ OVERCAME this error kindly assist... thanks! :)

Always throws UnimplementedError

With current Dart (2.12.2 - I don't know how it worked in the past) this line is always called as break only jumps out of switch, not a method. Because of that, there is always an error returned and printed into the console:

D:\SDK\Flutter\flutter\bin\cache\dart-sdk\bin\dart.exe --enable-asserts D:\Projects\Tutorials\Flutter\blockhero\tryout\lib\main-bloc.dart
lib/main-bloc.dart: Warning: Interpreting this as package URI, 'package:streams/main-bloc.dart'.
1
Unhandled exception:
Unhandled error UnimplementedError occurred in Instance of 'CounterBloc'.
#0 CounterBloc.mapEventToState (package:streams/main-bloc.dart:18:5)

#0 BlocBase.onError. (package:bloc/src/bloc.dart:389:7)
#1 BlocBase.onError (package:bloc/src/bloc.dart:390:6)
#2 _RootZone.runBinaryGuarded (dart:async/zone.dart:1558:10)
#3 _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:360:15)
#4 _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:378:16)
#5 _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:280:7)
#6 _SyncBroadcastStreamController._sendError. (dart:async/broadcast_stream_controller.dart:393:20)
#7 _BroadcastStreamController._forEachListener (dart:async/broadcast_stream_controller.dart:323:15)
#8 _SyncBroadcastStreamController._sendError (dart:async/broadcast_stream_controller.dart:392:5)
#9 _BroadcastStreamController._addError (dart:async/broadcast_stream_controller.dart:290:5)
#10 _RootZone.runBinaryGuarded (dart:async/zone.dart:1558:10)
#11 _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:360:15)
#12 _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:378:16)
#13 _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:280:7)
#14 _ForwardingStreamSubscription._addError (dart:async/stream_pipe.dart:128:11)
#15 _ForwardingStream._handleError (dart:async/stream_pipe.dart:95:10)
#16 _ForwardingStreamSubscription._handleError (dart:async/stream_pipe.dart:157:13)
#17 _RootZone.runBinaryGuarded (dart:async/zone.dart:1558:10)
#18 _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:360:15)
#19 _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:378:16)
#20 _DelayedError.perform (dart:async/stream_impl.dart:602:14)
#21 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:706:11)
#22 _PendingEvents.schedule. (dart:async/stream_impl.dart:663:7)
#23 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
#24 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
#25 _runPendingImmediateCallback (dart:isolate-patch/isolate_patch.dart:120:13)
#26 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:185:5)

Process finished with exit code 255

part #6 - snackbar showing up multi times

if navigate to second or third screen an press the increase or decrease button snackbar showing up one time and when you back to the previous screen snakbar showing up again same number of latest screen.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.