Loading...
Loading...
Manage state in your Flutter application
npx skill4agent add flutter/skills flutter-state-managementsetStateChangeNotifierproviderPageViewStatefulWidgetsetStateChangeNotifierproviderStatefulWidgetsetState()class LocalStateWidget extends StatefulWidget {
const LocalStateWidget({super.key});
State<LocalStateWidget> createState() => _LocalStateWidgetState();
}
class _LocalStateWidgetState extends State<LocalStateWidget> {
bool _isToggled = false;
void _handleToggle() {
// Validate-and-Fix: Ensure setState wraps the mutation.
setState(() {
_isToggled = !_isToggled;
});
}
Widget build(BuildContext context) {
return Switch(
value: _isToggled,
onChanged: (value) => _handleToggle(),
);
}
}class UserRepository {
Future<User> fetchUser(String id) async {
// Implementation for fetching user data
}
}ChangeNotifierclass UserViewModel extends ChangeNotifier {
UserViewModel({required this.userRepository});
final UserRepository userRepository;
User? _user;
User? get user => _user;
bool _isLoading = false;
bool get isLoading => _isLoading;
String? _errorMessage;
String? get errorMessage => _errorMessage;
// Command invoked by the UI
Future<void> loadUser(String id) async {
_isLoading = true;
_errorMessage = null;
notifyListeners(); // Trigger loading UI
try {
_user = await userRepository.fetchUser(id);
} catch (e) {
_errorMessage = e.toString();
} finally {
_isLoading = false;
notifyListeners(); // Trigger success/error UI
}
}
}providervoid main() {
runApp(
MultiProvider(
providers: [
Provider(create: (_) => UserRepository()),
ChangeNotifierProvider(
create: (context) => UserViewModel(
userRepository: context.read<UserRepository>(),
),
),
],
child: const MyApp(),
),
);
}Consumerclass UserProfileView extends StatelessWidget {
const UserProfileView({super.key});
Widget build(BuildContext context) {
return Scaffold(
body: Consumer<UserViewModel>(
builder: (context, viewModel, child) {
if (viewModel.isLoading) {
return const Center(child: CircularProgressIndicator());
}
if (viewModel.errorMessage != null) {
return Center(child: Text('Error: ${viewModel.errorMessage}'));
}
if (viewModel.user != null) {
return Center(child: Text('Hello, ${viewModel.user!.name}'));
}
return const Center(child: Text('No user loaded.'));
},
),
floatingActionButton: FloatingActionButton(
// Use listen: false when invoking commands outside the build method
onPressed: () => context.read<UserViewModel>().loadUser('123'),
child: const Icon(Icons.refresh),
),
);
}
}ConsumerStatelessWidgetStatefulWidgetProvider.of<T>(context)listen: truebuildConsumer<T>Selector<T, R>onPressedcontext.read<T>()Provider.of<T>(context, listen: false)notifyListeners()