Describe the bug
FirebaseAuth.instance.authStateChanges and FirebaseAuth.instance.userChanges always fires twice the first time i listen to it.
Steps to reproduce the behavior:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
debugPrint('main');
FirebaseAuth.instance.authStateChanges().listen((event) {
debugPrint('event ${event.toString()}');
});
runApp(MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('test'),
),
),
));
}
Notice flutter: event null is printed twice.
In my app i listen for a null event here before i sign in anonymously. When the event is fired twice, it caused a problem and a need for excess logic.
I'd appreciate if the stream would only fire once on initialization with either a null value or a User object. Or please explain why this fires twice.
Add any other context about the problem here.
Run flutter doctor and paste the output below:
Click To Expand
[✓] Flutter (Channel dev, 1.22.0-12.0.pre, on Mac OS X 10.15.6 19G2021, locale en-GB)
• Flutter version 1.22.0-12.0.pre at /Users/erlend/flutter
• Framework revision a27c242b0e (11 days ago), 2020-09-11 17:46:57 -0400
• Engine revision fee6f9e533
• Dart version 2.10.0 (build 2.10.0-110.0.dev)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
• Android SDK at /Users/erlend/Library/Android/sdk
• Platform android-29, build-tools 29.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 12.0)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 12.0, Build version 12A7209
• CocoaPods version 1.9.1
[✓] Android Studio (version 4.0)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 49.0.2
• Dart plugin version 193.7547
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
[✓] VS Code (version 1.49.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.8.1
[✓] Connected device (2 available)
• iPhone 8 (mobile) • 9FEC920D-59C8-4E42-A4DF-D0C9A091F9A6 • ios • com.apple.CoreSimulator.SimRuntime.iOS-14-0 (simulator)
• macOS (desktop) • macos • darwin-x64 • Mac OS X 10.15.6 19G2021
! Error: Erlend is not connected. Xcode will continue when Erlend is connected. (code -13)
• No issues found!
Run flutter pub deps -- --style=compact and paste the output below:
Click To Expand
Dart SDK 2.10.0-110.0.dev
Flutter SDK 1.22.0-12.0.pre
cashplan 1.0.0+24
dependencies:
- app_review 2.0.1 [http intl package_info url_launcher flutter]
- apple_sign_in 0.1.0 [flutter]
- charts_flutter 0.9.0 [charts_common collection flutter intl logging meta]
- cloud_firestore 0.14.0+2 [flutter meta quiver firebase_core firebase_core_platform_interface cloud_firestore_platform_interface cloud_firestore_web]
- csv_localizations 0.4.0+1 [flutter csv]
- cupertino_icons 1.0.0
- firebase_analytics 6.0.0 [meta flutter firebase_core firebase_analytics_web firebase_analytics_platform_interface]
- firebase_auth 0.18.0+1 [meta firebase_core firebase_core_platform_interface firebase_auth_platform_interface firebase_auth_web flutter]
- firebase_core 0.5.0 [firebase_core_platform_interface flutter quiver meta firebase_core_web]
- flutter 0.0.0 [characters collection meta typed_data vector_math sky_engine]
- flutter_local_notifications 1.4.4+4 [flutter platform flutter_local_notifications_platform_interface]
- flutter_localizations 0.0.0 [flutter intl characters collection meta path typed_data vector_math]
- geolocator 6.0.0+4 [flutter geolocator_platform_interface]
- get_it 5.0.0 [async meta]
- google_fonts 1.1.0 [flutter http path_provider crypto pedantic]
- google_maps_flutter 0.5.32 [flutter flutter_plugin_android_lifecycle google_maps_flutter_platform_interface]
- google_sign_in 4.5.3 [google_sign_in_platform_interface flutter meta google_sign_in_web]
- intl 0.16.1 [path]
- package_info 0.4.3 [flutter]
- path_provider 1.6.17 [flutter path_provider_platform_interface path_provider_macos path_provider_linux path_provider_windows]
- purchases_flutter 1.2.1 [flutter]
- rxdart 0.24.1
- shared_preferences 0.5.11 [meta flutter shared_preferences_platform_interface shared_preferences_linux shared_preferences_macos shared_preferences_web shared_preferences_windows]
dev dependencies:
- flutter_launcher_icons 0.8.0 [image args yaml]
- flutter_test 0.0.0 [flutter test_api path fake_async clock stack_trace vector_math async boolean_selector characters charcode collection matcher meta source_span stream_channel string_scanner term_glyph typed_data]
transitive dependencies:
- archive 2.0.13 [crypto args path]
- args 1.6.0
- async 2.5.0-nullsafety [collection]
- boolean_selector 2.1.0-nullsafety [source_span string_scanner]
- characters 1.1.0-nullsafety.2
- charcode 1.2.0-nullsafety
- charts_common 0.9.0 [collection intl logging meta vector_math]
- clock 1.1.0-nullsafety
- cloud_firestore_platform_interface 2.0.1 [flutter meta collection firebase_core plugin_platform_interface]
- cloud_firestore_web 0.2.0+1 [flutter flutter_web_plugins firebase http_parser meta firebase_core cloud_firestore_platform_interface js]
- collection 1.15.0-nullsafety.2
- convert 2.1.1 [charcode typed_data]
- crypto 2.1.4 [collection convert typed_data]
- csv 4.0.3
- fake_async 1.1.0-nullsafety [clock collection]
- ffi 0.1.3
- file 5.1.0 [intl meta path]
- firebase 7.3.0 [http http_parser js]
- firebase_analytics_platform_interface 1.0.3 [flutter meta]
- firebase_analytics_web 0.1.1 [flutter flutter_web_plugins firebase firebase_analytics_platform_interface meta]
- firebase_auth_platform_interface 2.0.1 [flutter meta firebase_core plugin_platform_interface]
- firebase_auth_web 0.3.0+1 [flutter flutter_web_plugins firebase meta http_parser intl firebase_core firebase_auth_platform_interface js]
- firebase_core_platform_interface 2.0.0 [flutter meta plugin_platform_interface quiver]
- firebase_core_web 0.2.0 [firebase firebase_core_platform_interface flutter flutter_web_plugins meta js]
- flutter_local_notifications_platform_interface 1.0.1 [flutter plugin_platform_interface]
- flutter_plugin_android_lifecycle 1.0.7 [flutter]
- flutter_web_plugins 0.0.0 [flutter characters collection meta typed_data vector_math]
- geolocator_platform_interface 1.0.4 [flutter meta plugin_platform_interface vector_math]
- google_maps_flutter_platform_interface 1.0.4 [flutter meta plugin_platform_interface stream_transform]
- google_sign_in_platform_interface 1.1.2 [flutter meta quiver]
- google_sign_in_web 0.9.1+1 [google_sign_in_platform_interface flutter flutter_web_plugins meta js]
- http 0.12.2 [http_parser path pedantic]
- http_parser 3.1.3 [charcode collection source_span string_scanner typed_data]
- image 2.1.13 [archive xml]
- js 0.6.1+1
- logging 0.11.4
- matcher 0.12.10-nullsafety [stack_trace]
- meta 1.3.0-nullsafety.2
- path 1.8.0-nullsafety
- path_provider_linux 0.0.1+1 [path xdg_directories path_provider_platform_interface flutter]
- path_provider_macos 0.0.4 [flutter]
- path_provider_platform_interface 1.0.3 [flutter meta platform plugin_platform_interface]
- path_provider_windows 0.0.4+1 [path_provider_platform_interface meta path flutter ffi win32]
- pedantic 1.9.0
- petitparser 3.0.4 [meta]
- platform 2.2.1
- platform_detect 1.4.0 [meta pub_semver]
- plugin_platform_interface 1.0.2 [meta]
- process 3.0.13 [file intl meta path platform]
- pub_semver 1.4.4 [collection]
- quiver 2.1.3 [matcher meta]
- shared_preferences_linux 0.0.2+1 [file flutter meta path path_provider_linux shared_preferences_platform_interface]
- shared_preferences_macos 0.0.1+6 [shared_preferences_platform_interface flutter]
- shared_preferences_platform_interface 1.0.3 [meta flutter]
- shared_preferences_web 0.1.2+4 [shared_preferences_platform_interface flutter flutter_web_plugins meta]
- shared_preferences_windows 0.0.1+1 [shared_preferences_platform_interface flutter ffi file meta path path_provider_platform_interface path_provider_windows]
- sky_engine 0.0.99
- source_span 1.8.0-nullsafety [charcode collection path term_glyph]
- stack_trace 1.10.0-nullsafety [path]
- stream_channel 2.1.0-nullsafety [async]
- stream_transform 1.2.0
- string_scanner 1.1.0-nullsafety [charcode source_span]
- term_glyph 1.2.0-nullsafety
- test_api 0.2.19-nullsafety [async boolean_selector collection meta path source_span stack_trace stream_channel string_scanner term_glyph matcher]
- typed_data 1.3.0-nullsafety.2 [collection]
- url_launcher 5.5.3 [flutter url_launcher_platform_interface url_launcher_web url_launcher_linux url_launcher_macos]
- url_launcher_linux 0.0.1+1 [flutter]
- url_launcher_macos 0.0.1+7 [flutter]
- url_launcher_platform_interface 1.0.8 [flutter meta plugin_platform_interface]
- url_launcher_web 0.1.3+2 [url_launcher_platform_interface platform_detect flutter flutter_web_plugins meta]
- vector_math 2.1.0-nullsafety.2
- win32 1.7.3 [ffi]
- xdg_directories 0.1.0 [path process flutter]
- xml 3.7.0 [collection convert meta petitparser]
- yaml 2.2.1 [charcode collection string_scanner source_span]
Hi @erf,
There's a similar open issue related to authStateChanges and currentUser, 3604.
Does it sound similar to your issue ?
Hi @darshankawar ,
Not quite the same. My issue is that authStateChanges and userChanges fires twice. I get the user object from those streams and don't care about currentUser.
Issue replicable on latest stable (1.20.4).
I/flutter (25761): main
I/flutter (25761): event null
I/flutter (25761): event null
flutter doctor -v
[✓] Flutter (Channel stable, 1.20.4, on Mac OS X 10.15.4 19E2269, locale en-IN)
• Flutter version 1.20.4 at /Users/dhs/documents/Fluttersdk/flutter
• Framework revision fba99f6cf9 (9 days ago), 2020-09-14 15:32:52 -0700
• Engine revision d1bc06f032
• Dart version 2.9.2
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.0)
• Android SDK at /Users/dhs/Library/Android/sdk
• Platform android-30, build-tools 30.0.0
• Java binary at: /Applications/Android
Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build
1.8.0_242-release-1644-b3-6222593)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.5, Build version 11E608c
• CocoaPods version 1.9.3
[✓] Android Studio (version 4.0)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 46.0.2
• Dart plugin version 193.7361
• Java version OpenJDK Runtime Environment (build
1.8.0_242-release-1644-b3-6222593)
[✓] VS Code (version 1.49.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.11.0
[!] Connected device
! No devices available
This is very annoying.
On the web, FirebaseAuth.instance.currentUser is always null after a page refresh.
After receiving the first 2 events, the correct value of currentUser gets populated.
Current workaround - put this in main.dart
Future<void> main() async {
await Firebase.initializeApp();
await waitForFirebaseAuth();
...
}
Future<void> waitForFirebaseAuth() async {
var count = 0;
await for (var user in FirebaseAuth.instance.authStateChanges()) {
print("firebase user: $user");
count += 1;
if (count >= 2) break;
}
}
Output -
firebase user: null
firebase user: User(...)
I faced the same issue. I use the following code alongside the rxdart library as a development workaround.
_streamSubscription = _auth
.authStateChanges()
// Used to prevent from authentication state firing twice.
.debounceTime(Duration(milliseconds: 10))
.listen((user) {
// ...
});
this does the trick, too:
_streamSubscription = _auth
.authStateChanges()
.distinct((p, n) => p.uid == n.uid) // ignore updates when the user id has not changed
.listen((user) {
// ...
});
this does the trick, too:
_streamSubscription = _auth .authStateChanges() .distinct((p, n) => p.uid == n.uid) // ignore updates when the user id has not changed .listen((user) { // ... });
That would block ALL user updates until user id changes? You probably don't want that. I just want to avoid the initial double event.
this does the trick, too:
_streamSubscription = _auth .authStateChanges() .distinct((p, n) => p.uid == n.uid) // ignore updates when the user id has not changed .listen((user) { // ... });That would block ALL user updates until user id changes? You probably don't want that. I just want to avoid the initial double event.
I see... then
.skip(1)
on the stream would do that.
this does the trick, too:
```
_streamSubscription = _auth
.authStateChanges().distinct((p, n) => p.uid == n.uid) // ignore updates when the user id has not changed.listen((user) {// ...
});
```
That would block ALL user updates until user id changes? You probably don't want that. I just want to avoid the initial double event.
I see... then
.skip(1)on the stream would do that.
That would work for now, but if firebase changes to only one initial event, there would be a problem..
@nimeacuerdo maybe this could work:
.userChanges()
.throttleTime(Duration(milliseconds: 300), trailing: true));
Good to know, @erf, although I'm not currently using rxdart
Same problem here, and it is quite annoying. The doc for authStateChanges() states that a null value is indication that the user is not currently logged in. The suggested workarounds do not take into account situtations where the user is not logged in and you actually want to react to the null value.