Describe the bug
LoginBloc is giving null inside the BlocBuilder from the Bloc Login Example
Expected behavior
I expected to open the loginForm.
Screenshots
If applicable, add screenshots to help explain your problem.
*Logs *
I/flutter ( 3542): βββ‘ EXCEPTION CAUGHT BY WIDGETS LIBRARY ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
I/flutter ( 3542): The following assertion was thrown building LoginForm(dirty, state: _LoginFormState#bace3):
I/flutter ( 3542): 'package:flutter_bloc/src/bloc_builder.dart': Failed assertion: line 22 pos 16: 'bloc != null': is
I/flutter ( 3542): not true.
I/flutter ( 3542):
I/flutter ( 3542): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter ( 3542): more information in this error message to help you determine and fix the underlying cause.
I/flutter ( 3542): In either case, please report this assertion by filing a bug on GitHub:
I/flutter ( 3542): https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter ( 3542):
I/flutter ( 3542): When the exception was thrown, this was the stack:
I/flutter ( 3542): #2 new BlocBuilder
package:flutter_bloc/src/bloc_builder.dart:22
I/flutter ( 3542): #3 _LoginFormState.build
package:concierge_app/β¦/widgets/login_form.dart:30
I/flutter ( 3542): #4 StatefulElement.build
package:flutter/β¦/widgets/framework.dart:3809
I/flutter ( 3542): #5 ComponentElement.performRebuild
package:flutter/β¦/widgets/framework.dart:3721
I/flutter ( 3542): #6 Element.rebuild
package:flutter/β¦/widgets/framework.dart:3547
I/flutter ( 3542): #7 ComponentElement._firstBuild
package:flutter/β¦/widgets/framework.dart:3701
I/flutter ( 3542): #8 StatefulElement._firstBuild
package:flutter/β¦/widgets/framework.dart:3848
I/flutter ( 3542): #9 ComponentElement.mount
package:flutter/β¦/widgets/framework.dart:3696
I/flutter ( 3542): #10 Element.inflateWidget
package:flutter/β¦/widgets/framework.dart:2950
I/flutter ( 3542): #11 Element.updateChild
package:flutter/β¦/widgets/framework.dart:2753
I/flutter ( 3542): #12 ComponentElement.performRebuild
package:flutter/β¦/widgets/framework.dart:3732
I/flutter ( 3542): #13 Element.rebuild
package:flutter/β¦/widgets/framework.dart:3547
I/flutter ( 3542): #14 ComponentElement._firstBuild
package:flutter/β¦/widgets/framework.dart:3701
I/flutter ( 3542): #15 ComponentElement.mount
package:flutter/β¦/widgets/framework.dart:3696
I/flutter ( 3542): #16 Element.inflateWidget
package:flutter/β¦/widgets/framework.dart:2950
I/flutter ( 3542): #17 Element.updateChild
package:flutter/β¦/widgets/framework.dart:2753
I/flutter ( 3542): #18 ComponentElement.performRebuild
package:flutter/β¦/widgets/framework.dart:3732
I/flutter ( 3542): #19 Element.rebuild
package:flutter/β¦/widgets/framework.dart:3547
I/flutter ( 3542): #20 ComponentElement._firstBuild
package:flutter/β¦/widgets/framework.dart:3701
I/flutter ( 3542): #21 ComponentElement.mount
package:flutter/β¦/widgets/framework.dart:3696
I/flutter ( 3542): #22 ParentDataElement.mount
package:flutter/β¦/widgets/framework.dart:4047
login_form.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../blocs/auth_bloc/authentification.dart';
import '../blocs/login_bloc/login.dart';
class LoginForm extends StatefulWidget {
final LoginBloc loginBloc;
final AuthenticationBloc authenticationBloc;
LoginForm({
Key key,
@required this.loginBloc,
@required this.authenticationBloc,
}) : super(key: key);
@override
State
}
class _LoginFormState extends State
final _usernameController = TextEditingController();
final _passwordController = TextEditingController();
LoginBloc get _loginBloc => widget.loginBloc;
@override
Widget build(BuildContext context) {
return BlocBuilder
bloc: _loginBloc,
builder: (
BuildContext context,
LoginState state,
) {
if (state is LoginFailure) {
_onWidgetDidBuild(() {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('${state.error}'),
backgroundColor: Colors.red,
),
);
});
}
return Form(
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'username'),
controller: _usernameController,
),
TextFormField(
decoration: InputDecoration(labelText: 'password'),
controller: _passwordController,
obscureText: true,
),
RaisedButton(
onPressed:
state is! LoginLoading ? _onLoginButtonPressed : null,
child: Text('Login'),
),
Container(
child:
state is LoginLoading ? CircularProgressIndicator() : null,
),
],
),
);
},
);
}
void _onWidgetDidBuild(Function callback) {
WidgetsBinding.instance.addPostFrameCallback((_) {
callback();
});
}
void _onLoginButtonPressed() {
_loginBloc.dispatch(LoginButtonPressed(
username: _usernameController.text,
password: _passwordController.text,
));
}
}
login_bloc.dart
import 'dart:async';
import 'package:meta/meta.dart';
import 'package:bloc/bloc.dart';
import '../../services/loginRepository.dart';
import '../auth_bloc/authentification.dart';
import './login.dart';
class LoginBloc extends Bloc
final LoginRepository loginRepository;
final AuthenticationBloc authenticationBloc;
LoginBloc({
@required this.loginRepository,
@required this.authenticationBloc,
}) : assert(loginRepository != null),
assert(authenticationBloc != null);
@override
LoginState get initialState => LoginInitial();
@override
Stream
LoginState currentState,
LoginEvent event,
) async* {
if (event is LoginButtonPressed) {
yield LoginLoading();
try {
final token = await loginRepository.authenticate(
username: event.username,
password: event.password,
);
authenticationBloc.dispatch(LoggedIn(token: token));
yield LoginInitial();
} catch (error) {
yield LoginFailure(error: error.toString());
}
}
}
}
Can you please share the code for how LoginBloc gets passed to LoginForm? Iβm guessing itβs not being injected correctly. Please include login_page.dart as well as main.dart
solved
It was not injected correctly in build function located in login_page.dart
Thank's
solved
It was not injected correctly in build function located in login_page.dart
Thank's
@MarcioQuimbundo Can you elaborate on how you did the right injection please? I am having a similar issue where bloc becomes null after the first mapEventToState
@aytunch are you able to share your code? I can take a look and try to help π
@felangel i will post the project soon in a new issue
@felangel @aytunch i am using login example "https://github.com/felangel/bloc/tree/master/examples/flutter_firebase_login"
Not did any modification , I am getting same issue. Please can you explian what's wrong with it...
Failed assertion: line 44 pos 16: 'bloc != null': is not true.
@zubyf09 the examples are using flutter_bloc v0.20.0 which does not require a bloc in BlocBuilder or BlocListener. Can you please make sure youβre using v0.20.0?
@felangel thanks for your Help. I was using flutter_bloc: ^0.18.3.
After updating it to v0.20.0 my issue is resolved.
@felangel Can you elaborate on how you did the right injection please? I am facing a similar issue with the context, it always is returnder as dirty.
@JCFlores93 can you provide a sample app which reproduces the issue?
void main() async {
FlutterError.onError = (FlutterErrorDetails details) {
if (isInDebugMode) {
FlutterError.dumpErrorToConsole(details);
} else {
Zone.current.handleUncaughtError(details.exception, details.stack);
}
};
WidgetsFlutterBinding.ensureInitialized();
await FlutterCrashlytics().initialize();
runZoned
runApp(MultiBlocProvider(
providers: [
BlocProvider
builder: (context) => PostsBloc(),
),
BlocProvider
builder: (context) => CurrentUserBloc(),
)
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: _buildTheme(),
initialRoute: '/',
routes: {
'/': (context) => MenuContainer(),
},
),
));
}, onError: (error, stackTrace) async {
await FlutterCrashlytics()
.reportCrash(error, stackTrace, forceCrash: false);
});
}
@felangel The first provider works fine, but the second it's not working. I think it could be a problem of DI. Because the first bloc is called in the MenuContainer and the second bloc is other widget.
`class MenuContainer extends StatefulWidget {
MenuContainer();
@override
_MenuState createState() => new _MenuState();
}
class _MenuState extends State
PostsBloc _postsBloc;
@override
void initState() {
super.initState();
_postsBloc = BlocProvider.of
_postsBloc.dispatch(LoadPosts());
}
_MenuState();
int _selectedIndex = 0;
List
return [
QueriesAnimalContainer(posts: posts, refresh: _refresh),
SearchContainer(posts: posts, refresh: _refresh),
PostScreenContainer(),
LoginContainer(),
];
}
@override
Widget build(BuildContext context) {
return BlocBuilder(
bloc: _postsBloc,
builder: (BuildContext context, PostState state) {
if (state is PostsLoading) {
return Center(
child: CircularProgressIndicator(),
);
} else if (state is PostsLoaded) {
final widgetOptions = createTabOptions(posts: state.posts);
return Scaffold(
backgroundColor: Theme.of(context).primaryColor,
bottomNavigationBar: BottomNavigatorBar(
selectedIndex: _selectedIndex, onItemTapped: _onItemTapped),
body: SafeArea(
child:
Center(child: widgetOptions.elementAt(_selectedIndex))),
);
}
return Container(height: .0, width: .0);
});
}
`
@JCFlores93 when you use MultiBlocProvider you need to explicitly provide the types for each BlocProvider like:
MultiBlocProvider(
providers: [
BlocProvider< PostsBloc>(
builder: (context) => PostsBloc(),
),
BlocProvider<CurrentUserBloc>(
builder: (context) => CurrentUserBloc(),
),
],
child: ...
Also when you're looking up the bloc via BlocProvider you also need to specify the type:
_postsBloc = BlocProvider.of<PostsBloc>(context);
Hope that helps π
@felangel where the context is dirty is in LoginContainer.
@JCFlores93 when you use
MultiBlocProvideryou need to explicitly provide the types for eachBlocProviderlike:MultiBlocProvider( providers: [ BlocProvider< PostsBloc>( builder: (context) => PostsBloc(), ), BlocProvider<CurrentUserBloc>( builder: (context) => CurrentUserBloc(), ), ], child: ...Also when you're looking up the bloc via
BlocProvideryou also need to specify the type:_postsBloc = BlocProvider.of<PostsBloc>(context);Hope that helps
Yes. I did it.
@felangel I having issues when I look for the second one in LoginContainer. The state always arrives null, but the CurrentUserState contains props, but in LoginContainer is always null
@override
Widget build(BuildContext context) {
_currentUserBloc = BlocProvider.of
return BlocBuilder(
bloc: _currentUserBloc,
builder: ( context, CurrentUserState state) {
....
}
@JCFlores93 as I mentioned, you need to specify the type when doing a lookup using BlocProvider.
You can't just use BlocProvider.of(context) because there's no way for the bloc library to know which bloc you want.
You have to specify the type like:
BlocProvider.of<CurrentUserBloc>(context);
Most helpful comment
@felangel thanks for your Help. I was using flutter_bloc: ^0.18.3.
After updating it to v0.20.0 my issue is resolved.