0
0
Fluttermobile~5 mins

Service locator pattern in Flutter

Choose your learning style9 modes available
Introduction

The service locator pattern helps you find and use services or objects easily in your app without passing them everywhere. It keeps your code clean and simple.

When you want to share a single instance of a service across many parts of your app.
When you want to avoid passing objects through many layers of widgets or classes.
When you want to easily swap or mock services during testing.
When you want to organize your app dependencies in one place.
When you want to reduce tight coupling between classes.
Syntax
Flutter
final locator = GetIt.instance;

// Register a service
locator.registerLazySingleton<Service>(() => ServiceImplementation());

// Use the service
final service = locator<Service>();

Use registerLazySingleton to create the service only when needed.

Use locator() to get the registered service anywhere in your code.

Examples
This example registers a Logger service as a singleton and uses it to log a message.
Flutter
final locator = GetIt.instance;

// Register a service
locator.registerSingleton<Logger>(Logger());

// Access the service
final logger = locator<Logger>();
logger.log('App started');
This example registers ApiService lazily, so it is created only when first used.
Flutter
final locator = GetIt.instance;

// Register a service lazily
locator.registerLazySingleton<ApiService>(() => ApiServiceImpl());

// Later in the code
final api = locator<ApiService>();
api.fetchData();
Sample App

This test shows how the service locator provides the same CounterService instance everywhere. Incrementing count from one reference affects the other.

Flutter
import 'package:get_it/get_it.dart';

class CounterService {
  int count = 0;
  void increment() => count++;
}

void main() {
  final locator = GetIt.instance;

  // Register the CounterService
  locator.registerLazySingleton<CounterService>(() => CounterService());

  // Get the service and use it
  final counter1 = locator<CounterService>();
  counter1.increment();
  counter1.increment();

  // Get the service again
  final counter2 = locator<CounterService>();

  print('Counter1 count: ${counter1.count}');
  print('Counter2 count: ${counter2.count}');

  // Check if both are the same instance
  print('Same instance: ${identical(counter1, counter2)}');
}
OutputSuccess
Important Notes

Always register services before using them to avoid errors.

Use service locator carefully to avoid hiding dependencies, which can make testing harder.

For testing, you can replace services in the locator with mock versions easily.

Summary

The service locator pattern helps manage and access shared services easily.

It reduces the need to pass objects through many layers.

It supports better testing by allowing easy swapping of services.