I am too comfortable using Flutter Bloc as state management library for all my Flutter application but recently I have to collaborate with developers who wanted to user Provider as our application state management library. BlocProvider in FlutterBloc is equivalent to ChangeNotifierProvider in Provider, while Consumer in Provider behaves similarly to BlocBuilder in Flutter Bloc. However, there is no equivalent of BlocListener in Provider. How do developers usually handle business logic error in Provider state management library while Flutter Bloc developers usually just emit a bloc state which is an error state and the BlocListener will handle the state to display an error dialog or show a snackbar.
Is there a better solution other than this?
void providerListener() {
pageController.animateToPage(context.read<Catalog>().isService ? 0 : 1,
duration: const Duration(milliseconds: 200), curve: Curves.easeInOut);
}
@override
void initState() {
pageController = PageController(initialPage: context.read<Catalog>().isService ? 0 : 1);
context.read<Catalog>().addListener(providerListener);
super.initState();
}
@override
void dispose() {
context.read<Catalog>().removeListener(providerListener);
super.dispose();
}
providerListener will behave like a BlocListener...
You can use match package and an enum to do changes on the screen where you are interested. An then do something like that:
import 'package:flutter/material.dart';
import 'package:match/match.dart';
part 'login_controller.g.dart';
@match
enum LoginStatus {
initial,
success,
login,
loading,
loginError,
error,
}
class LoginController extends ChangeNotifier {
String email = "victor@gmail.com";
String password = "123456";
LoginStatus status = LoginStatus.initial;
LoginController({
this.status = LoginStatus.initial,
});
void login(String email, String password) {
status = LoginStatus.loading;
if (email == this.email && password == this.password) {
status = LoginStatus.success;
notifyListeners();
// return true;
} else {
status = LoginStatus.error;
notifyListeners();
// return false;
}
}
}
Center(
child: SizedBox(
width: 150,
height: 45,
child: Consumer<LoginController>(
builder: (context, controller, child) {
WidgetsBinding.instance.addPostFrameCallback((_) {
controller.status.matchAny(
any: () => hideLoader(),
loading: () => showLoader(),
error: () {
hideLoader();
showError(
"Não foi possível fazer o login. Tente Novamente!",
);
},
success: () {
hideLoader();
Navigator.of(context).pushNamed("/welcome");
},
);
});
return ElevatedButton(
child: const Text("ENTRAR"),
onPressed: () {
final bool valid =
_formKey.currentState?.validate() ?? false;
if (valid) {
controller.login(
_emailEC.text,
_passwordEC.text,
);
}
},
);
},
),
),
),