diff --git a/packages/firebase_remote_config/CHANGELOG.md b/packages/firebase_remote_config/CHANGELOG.md index 7d114c78c614..b5e1ea6bc918 100644 --- a/packages/firebase_remote_config/CHANGELOG.md +++ b/packages/firebase_remote_config/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.3.0+4 + +* Fix `Bad state: Future already completed` error when initially + calling `RemoteConfig.instance` multiple times in parallel. + ## 0.3.0+3 * Replace deprecated `getFlutterEngine` call on Android. diff --git a/packages/firebase_remote_config/lib/src/remote_config.dart b/packages/firebase_remote_config/lib/src/remote_config.dart index 161a2b5b1447..9bd461eb6352 100644 --- a/packages/firebase_remote_config/lib/src/remote_config.dart +++ b/packages/firebase_remote_config/lib/src/remote_config.dart @@ -25,17 +25,23 @@ class RemoteConfig extends ChangeNotifier { RemoteConfigSettings _remoteConfigSettings; DateTime get lastFetchTime => _lastFetchTime; + LastFetchStatus get lastFetchStatus => _lastFetchStatus; + RemoteConfigSettings get remoteConfigSettings => _remoteConfigSettings; - static Completer _instanceCompleter = Completer(); + @visibleForTesting + static Completer instanceCompleter = Completer(); /// Gets the instance of RemoteConfig for the default Firebase app. static Future get instance async { - if (!_instanceCompleter.isCompleted) { - _instanceCompleter.complete(await _getRemoteConfigInstance()); + if (!instanceCompleter.isCompleted) { + final _remoteConfigInstance = await _getRemoteConfigInstance(); + if (!instanceCompleter.isCompleted) { + instanceCompleter.complete(_remoteConfigInstance); + } } - return _instanceCompleter.future; + return instanceCompleter.future; } static Future _getRemoteConfigInstance() async { diff --git a/packages/firebase_remote_config/test/firebase_remote_config_test.dart b/packages/firebase_remote_config/test/firebase_remote_config_test.dart index 937ac98a5d8d..f5965761191b 100644 --- a/packages/firebase_remote_config/test/firebase_remote_config_test.dart +++ b/packages/firebase_remote_config/test/firebase_remote_config_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; + import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -40,6 +42,12 @@ void main() { }); }); + tearDown(() { + RemoteConfig.instanceCompleter = Completer(); + // empty log for next tests + log.removeWhere((_) => true); + }); + test('instance', () async { final RemoteConfig remoteConfig = await RemoteConfig.instance; expect( @@ -59,10 +67,12 @@ void main() { RemoteConfig.instance, RemoteConfig.instance, ]; - Future.wait(futures).then((List remoteConfigs) { - // Check that both returned Remote Config instances are the same. - expect(remoteConfigs[0], remoteConfigs[1]); - }); + final List remoteConfigs = await Future.wait(futures); + // Check that both returned Remote Config instances are the same. + expect(remoteConfigs[0], remoteConfigs[1]); + // Check that method RemoteConfig#instance was called at least once + expect(log.length, isPositive); + expect(log[0], isMethodCall('RemoteConfig#instance', arguments: null)); }); });