import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CounterViewModel extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
void decrement() {
_count--;
notifyListeners();
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => CounterViewModel(),
child: const MaterialApp(
home: CounterScreen(),
),
);
}
}
class CounterScreen extends StatelessWidget {
const CounterScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter MVVM')),
body: Center(
child: Consumer<CounterViewModel>(
builder: (context, viewModel, child) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${viewModel.count}',
style: const TextStyle(fontSize: 48),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: viewModel.decrement,
child: const Text('-'),
),
const SizedBox(width: 20),
ElevatedButton(
onPressed: viewModel.increment,
child: const Text('+'),
),
],
),
],
);
},
),
),
);
}
}
This app uses the MVVM pattern by separating the UI (View) from the business logic (ViewModel). The CounterViewModel class holds the counter state and methods to change it. It extends ChangeNotifier so it can notify the UI when the data changes.
The MyApp widget provides the ViewModel to the widget tree using ChangeNotifierProvider from the provider package.
The CounterScreen widget listens to the ViewModel using Consumer. It rebuilds the UI when the count changes, showing the current count and two buttons to increment or decrement the value.
This clear separation makes the app easier to maintain and test.