The “instance” getter on the ServicesBinding binding mixin is only available once that binding has been initialized.

When working with Flutter, you may encounter an error message that says “The ‘instance’ getter on the ServicesBinding binding mixin is only available once that binding has been initialized”. This error can occur when using packages like Shared Preferences that rely on the Flutter framework’s ServicesBinding to function correctly.

Why Does the ServicesBinding Error Occur?

To demonstrate why the error occurs we have the below code snippet.

import 'package:shared_preferences/shared_preferences.dart';

Future<void> main() async {
  SharedPreferences preferences = await SharedPreferences.getInstance();

  preferences.setString('key', 'value');
}

In this code, snippet we import the Shared Preferences package and try to retrieve an instance of the SharedPreferences class and assign it to the preferences variable. The main is asynchronous because the getInstance function returns a Future. At last, we are trying to save a new String inside the shared preferences.

However, when running the code we will encounter the “ServicesBinding binding mixin is only available once” error. This happens because, in Flutter, the ServiceBinding is responsible for initializing and managing various framework services.

The Shared Preferences package relies on the ServiceBinding to initialize the shared preferences service before it can be used. Normally the initialization in Flutter applications happens when we call the runApp function.

void runApp(Widget app) {
  final WidgetsBinding binding = WidgetsFlutterBinding.ensureInitialized();
  assert(binding.debugCheckZone('runApp'));
  binding
    ..scheduleAttachRootWidget(binding.wrapWithDefaultView(app))
    ..scheduleWarmUpFrame();
}

However, sometimes you want to perform actions before you call the runApp function. Therefore let us have a look at the following section where we go over the solution.

Solve the ServicesBinding Error

The previous section might already have spoiled the solution for the “ServicesBinding binding mixin is only available once” error, but instead of waiting for the runApp function to call the WidgetsFlutterBinding.ensureInitialized function. We want to call it ourselves.

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  SharedPreferences preferences = await SharedPreferences.getInstance();

  preferences.setString('key', 'value');
}

In this updated code snippet, we call the WidgetsFlutterBinding.ensureInitialized function to ensure that Flutter’s ServiceBinding is ready. After that, we can use the SharedPreferences class without running into any problems.

In test cases you can use TestWidgetsFlutterBinding.ensureInitialized. This function will use a fake http client that always returns a status code of 400. This is to prevent tests from making actual network calls.

Conclusion

In Flutter, it is important to ensure that the framework’s ServiceBinding is ready before running your code. This includes packages that rely on how Flutter works internally. By using the WidgetsFlutterBinding.ensureInitialized function, you can prevent running into ServiceBinding related errors.

Tijn van den Eijnde
Tijn van den Eijnde
Articles: 41

Leave a Reply

Your email address will not be published. Required fields are marked *