What is the best practice in flutter, should each Widget have a controller attached to it or the Widget can have also presentation logic inside?
As an example shown here is some chatGPT generated code for a login widget (so please ignore if some parts are incorrect). If the user is logged in it will show logout button or login button when is logged out.
// Create a Riverpod provider for the authentication state
final authProvider = ChangeNotifierProvider<AuthController, bool>((ref) {
return AuthController();
});
class AuthController extends ChangeNotifier {
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Authentication Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Welcome to the App!',
),
SizedBox(height: 20),
Consumer(
builder: (context, watch, child) {
final isAuthenticated = watch(authProvider);
return Column(
children: [
if (!isAuthenticated) <----- here
ElevatedButton(
onPressed: () {
context.read(authProvider.notifier).login();
},
child: Text('Login'),
),
if (isAuthenticated) <----- here
ElevatedButton(
onPressed: () {
context.read(authProvider.notifier).logout();
},
child: Text('Logout'),
),
],
In this case the Widget will react to a Riverpod provider and when update it’s UI. I’ve marked where the Widget decides what to show base on the info from the provider.
Does it make sense to have an extra controller object that communicates with the provider and updates the UI in this case?
Thanks
2
Answers
Generally, the best practice is to either keep all the controllers in a folder named controller or inside a method folder wherein it contains method_screen.dart, method_model.dart & method_controller.dart. These are very efficient practices for debugging and for quick and easy update purpose.
Also in this case it acts as an object to get called from the function. So yes it’s necessary to have the controller.
The use case for
Notifier
is exactly what you are indicating, to have an object (service, controller, …) which handles and notifies for changes in a data model which is provided by a provider.You can even have a getter ("view" in the example) to expose the current state from the notifier (controller). Beware that state exposed by the notifier it will not notify the listeners when the state changes. You shall use the actual provider for that purpose.
Then in your code, wherever you need to have a controller you would:
That "controller" can be passed as argument to functions or widgets as any other object.