srawlins / timezone

Time zone database and time zone aware DateTime object for Dart.
BSD 2-Clause "Simplified" License
101 stars 52 forks source link

Can't use Flutter's `compute()` to call `initializeTimeZones()` in a new isolate #154

Open omarsahl opened 1 year ago

omarsahl commented 1 year ago

Hello @srawlins, thank you for the very helpful library.

I was trying to use flutter's compute function to move the initialization process to a new isolate using the following code:

void _initTimeZones([_]) {
  return initializeTimeZones();
}

Future<void> asyncInitTimeZones() {
  return compute(_initTimeZones, null);
}

The problem is that the current implementation of env.dart uses a global variable for LocationDatabase which doesn't work well with isolates, I believe.

The second test of the following two tests fails and throws a LocationNotFoundException.

void main() {
  test('timezone sync initialization', () {
    initializeTimeZones();
    final location = tz.getLocation('Asia/Novosibirsk');
    expect(location.name, equals('Asia/Novosibirsk'));
  });

  test('timezone async initialization', () async {
    await asyncInitTimeZones();
    final location = tz.getLocation('Asia/Novosibirsk');
    expect(location.name, equals('Asia/Novosibirsk'));
  });
}
SungHyun22 commented 1 year ago

Same issue here

jamesncl commented 1 year ago

There were various problems using plugins from isolates prior to Flutter 3.7, which aren't really an issue with this package but a limitation of flutter itself. Try updating to 3.7 or later and this should be resolved - see this excellent blogpost for a full explanation

Take particular note of the use of BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken) and also use DartPluginRegistrant.ensureInitialized() and you should be good to go. I've been initialising timezones in flutter 3.7 in isolates and have no problems.