import 'package:flutter/material.dart';
class User {
final String name;
final String email;
User(this.name, this.email);
}
abstract class UserService {
Future<User> fetchUser();
}
class RealUserService implements UserService {
@override
Future<User> fetchUser() async {
await Future.delayed(Duration(seconds: 2));
return User('Alice', 'alice@example.com');
}
}
class MockUserService implements UserService {
@override
Future<User> fetchUser() async {
// Return instantly with fixed data
return User('Mock Bob', 'mockbob@example.com');
}
}
class UserProfileScreen extends StatefulWidget {
final UserService userService;
const UserProfileScreen({super.key, required this.userService});
@override
State<UserProfileScreen> createState() => _UserProfileScreenState();
}
class _UserProfileScreenState extends State<UserProfileScreen> {
User? user;
bool loading = true;
@override
void initState() {
super.initState();
_loadUser();
}
Future<void> _loadUser() async {
setState(() {
loading = true;
});
User fetchedUser = await widget.userService.fetchUser();
setState(() {
user = fetchedUser;
loading = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('User Profile')),
body: Center(
child: loading
? CircularProgressIndicator()
: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Name: ${user?.name ?? ''}'),
Text('Email: ${user?.email ?? ''}'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _loadUser,
child: Text('Refresh'),
),
],
),
),
);
}
}
void main() {
// Switch between RealUserService and MockUserService here
bool useMock = true;
runApp(MaterialApp(
home: UserProfileScreen(
userService: useMock ? MockUserService() : RealUserService(),
),
));
}
We created a MockUserService that implements UserService and returns fixed user data immediately. This allows us to test the UI without waiting for network delays.
In UserProfileScreen, we use the injected userService to fetch user data asynchronously in _loadUser(). We update the loading state to show a spinner while fetching.
The main() function demonstrates switching between the real and mock services by toggling the useMock boolean. This shows how dependency injection helps us replace real services with mocks easily.