Closed zeshuaro closed 2 years ago
Hi @zeshuaro 👋 Thanks for opening an issue!
emit
is intended for use only within the bloc/cubit instance itself. I highly advise against using extensions
here and instead consider using something like a mixin:
class MainCubit extends Cubit<MainState> {
MainCubit() : super(MainState());
void foo() {
emit(state);
}
}
mixin BooMixin on MainCubit {
void boo() {
emit(someState);
}
}
Let me know if that helps and sorry for any inconvenience!
Thanks for your reply and suggestion. Also there's no need to apologise.
Using a mixin did help me to get around with the error messages. But this is my first time using mixin and I have a follow-up question.
For the code below, I could call the method boo
within context.read<FooCubit>()
previously with extension, but I can't do it now with mixin. Would you be able to have a look and see what am I missing?
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class FooCubit extends Cubit<FooState> {
FooCubit() : super(FooState());
void foo() {
emit(state);
}
}
class FooState {}
mixin BooCubit on FooCubit {
void boo() {
emit(state);
}
}
class FooWidget extends StatelessWidget {
const FooWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocListener<FooCubit, FooState>(
listener: (context, state) {
context.read<FooCubit>().boo();
},
child: Container(),
);
}
}
import 'package:bloc/bloc.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class FooCubit extends Cubit<FooState> { FooCubit() : super(FooState()); void foo() { emit(state); } } class FooState {} mixin BooCubit on FooCubit { void boo() { emit(state); } } class FooWidget extends StatelessWidget { const FooWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocListener<FooCubit, FooState>( listener: (context, state) { context.read<FooCubit>().boo(); }, child: Container(), ); } }
Yup you'd just need to use context.read<BooCubit>().boo()
instead. Let me know if that helps 👍
Closing for now but feel free to comment with any additional questions and I'm happy to continue the conversation 👍
I tried your suggestion with context.read<BooCubit>().boo()
but I got the following error:
Could not find the correct Provider<BooCubit> above this BlocBuilder
And I couldn't initiate a BooCubit
instance to the BlocProvider
as it's an mixin so I'm not sure how to make BooCubit
available for the lookup.
In addition, I face a similar issue when trying to update the unit tests with using the mixin. Again I can't call boo from the cubit. If I update the code to blocTest<BooCubit, FooState>
, then I need to initiate BooCubit
which is not possible as it's a mixin.
void main() {
late FooCubit cubit;
setUp(() {
cubit = FooCubit();
});
group('boo test', () {
blocTest<FooCubit, FooState>(
'should emit boo state',
build: () => cubit,
act: (cubit) => cubit.boo(),
expect: () => [FooState()],
);
});
Do you have any thoughts on this?
Description
Would you be able to explain the reason for annotating the
emit
method with@protected
(source)?I have been using a very large cubit (with lots of methods/events). To make the code easier to read, I split it up by using separate files and extensions. For example:
This has been working fine until the latest update to v8.0.0, where the
emit
method is now marked with@protected
. The analysis tool now complains that theemit
method cannot be used in the extension class.I can ignore this linting rule but I'll rather not if this can be updated in the
bloc
package. If not, is there another workaround for this use case?