Rob Lyndon
Rob Lyndon

Reputation: 12661

Flutter: Failing to combine localisation with Provider package

I'm trying to use localisation so that it is available from within my own Flutter plugin. To do this, I'm using an abstract base class called CoreLocalisation, which is implemented by my concrete AppLocalisation class. Then I'm using

List<SingleChildCloneableWidget> uiConsumableProviders = <SingleChildCloneableWidget>[
  ...
  Provider<CoreLocalisation>(
    create: (context) => AppLocalisation.of(context)
  )
];

I'm calling the MultiProvider from a ContentPage:

@override Widget build(BuildContext context) {
  //final localisation = AppLocalisation.of(context);
  return MultiProvider(
    providers: uiConsumableProviders,
    child: ...
  );
}

What is confusing me is that the commented out call to AppLocalisation.of(context) works perfectly, but the invocation within the MultiProvider throws the following exception:

FlutterError (inheritFromWidgetOfExactType(_LocalizationsScope) or inheritFromElement() was called before BuilderStateDelegate.initDelegate() completed.

In my understanding, the child context should have access to all of the elements available to the parent context. Am I missing something fundamental?

Upvotes: 1

Views: 163

Answers (2)

Rob Lyndon
Rob Lyndon

Reputation: 12661

I didn't solve the problem explicitly, but I set up a workaround. First of all, I created a provider whose job was simply to convert a context into a concrete instance of CoreLocalisation. It used this class in the plugin:

class CoreLocalisationProvider {
  final CoreLocalisation Function(BuildContext) of;

  CoreLocalisationProvider(this.of);
}

Then the provider in the consuming app looked like this:

Provider<CoreLocalisationProvider>.value(value: CoreLocalisationProvider((context) => AppLocalisation.of(context)))

and I can add the following syntactic sugar to CoreLocalisation:

static CoreLocalisation of(BuildContext context) => Provider.of<CoreLocalisationProvider>(context).of(context);

This admittedly looks clumsy, but it permits me to use the familiar syntax CoreLocalisation.of(context) throughout the codebase, as if CoreLocalisation were a common-or-garden concrete localisation class.

Upvotes: 0

Igor Kharakhordin
Igor Kharakhordin

Reputation: 9903

You can't call Localizations.of (which calls inheritFromWidgetOfExactType) synchronously inside of initState, because the widget tree is still being built in that moment and you can't access inherited widget. You can call it using asynchronous callback:

Timer.run(() {
  AppLocalizations.of(this.context);
});

or from post-frame callback:

WidgetsBinding.instance.addPostFrameCallback((_) {
  AppLocalizations.of(this.context);
});

Upvotes: 1

Related Questions