0
0
Fluttermobile~20 mins

Service locator pattern in Flutter - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Service Locator Demo
This screen demonstrates how to use the service locator pattern to access a simple greeting service from anywhere in the app.
Target UI
-------------------------
| Service Locator Demo   |
|-----------------------|
| Greeting:             |
|                       |
| [Show Greeting]       |
|                       |
-------------------------
Create a simple GreetingService class with a method that returns a greeting string.
Use a service locator to register and retrieve the GreetingService instance.
Build a screen with a button labeled 'Show Greeting'.
When the button is pressed, display the greeting text below the label 'Greeting:'.
Use the service locator to get the GreetingService inside the widget.
Starter Code
Flutter
import 'package:flutter/material.dart';

// TODO: Create GreetingService class

// TODO: Create ServiceLocator class with register and get methods

void main() {
  // TODO: Register GreetingService instance
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: ServiceLocatorDemo(),
    );
  }
}

class ServiceLocatorDemo extends StatefulWidget {
  const ServiceLocatorDemo({super.key});

  @override
  State<ServiceLocatorDemo> createState() => _ServiceLocatorDemoState();
}

class _ServiceLocatorDemoState extends State<ServiceLocatorDemo> {
  String greeting = '';

  void _showGreeting() {
    // TODO: Use service locator to get GreetingService and update greeting
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Service Locator Demo')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text('Greeting:'),
            const SizedBox(height: 8),
            Text(greeting, style: const TextStyle(fontSize: 18)),
            const SizedBox(height: 24),
            ElevatedButton(
              onPressed: _showGreeting,
              child: const Text('Show Greeting'),
            ),
          ],
        ),
      ),
    );
  }
}
Task 1
Task 2
Task 3
Task 4
Solution
Flutter
import 'package:flutter/material.dart';

class GreetingService {
  String getGreeting() => 'Hello from Service Locator!';
}

class ServiceLocator {
  static final Map<Type, Object> _services = {};

  static void register<T>(T service) {
    _services[T] = service!;
  }

  static T get<T>() {
    final service = _services[T];
    if (service == null) {
      throw Exception('Service of type $T not found');
    }
    return service as T;
  }
}

void main() {
  ServiceLocator.register<GreetingService>(GreetingService());
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: ServiceLocatorDemo(),
    );
  }
}

class ServiceLocatorDemo extends StatefulWidget {
  const ServiceLocatorDemo({super.key});

  @override
  State<ServiceLocatorDemo> createState() => _ServiceLocatorDemoState();
}

class _ServiceLocatorDemoState extends State<ServiceLocatorDemo> {
  String greeting = '';

  void _showGreeting() {
    final service = ServiceLocator.get<GreetingService>();
    setState(() {
      greeting = service.getGreeting();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Service Locator Demo')),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text('Greeting:'),
            const SizedBox(height: 8),
            Text(greeting, style: const TextStyle(fontSize: 18)),
            const SizedBox(height: 24),
            ElevatedButton(
              onPressed: _showGreeting,
              child: const Text('Show Greeting'),
            ),
          ],
        ),
      ),
    );
  }
}

We created a GreetingService class that returns a greeting string. The ServiceLocator class holds a map of services by their type. We register the GreetingService instance in main(). Inside the widget, when the button is pressed, we get the service from the locator and update the UI with the greeting. This pattern lets us access shared services easily from anywhere without passing them around.

Final Result
Completed Screen
-------------------------
| Service Locator Demo   |
|-----------------------|
| Greeting:             |
| Hello from Service    |
| Locator!              |
|                       |
| [Show Greeting]       |
|                       |
-------------------------
User taps 'Show Greeting' button.
Greeting text below 'Greeting:' updates to 'Hello from Service Locator!'.
Stretch Goal
Add a second service called TimeService that returns the current time as a string. Add another button 'Show Time' that displays the current time below the greeting.
💡 Hint
Create TimeService with a method getCurrentTime() returning DateTime.now().toLocal().toString(). Register it in ServiceLocator. Add a new button and use setState to show the time.