From 8fe10ab65113250f297eab5478b6523e7d396cac Mon Sep 17 00:00:00 2001 From: realth000 Date: Tue, 5 Dec 2023 22:25:10 +0800 Subject: [PATCH] fix(*): Fix ref used after dispose and stream used after closed --- lib/models/cookie_data.dart | 31 ++++++++++++++---------- lib/providers/cookie_provider.dart | 38 +++++++++++------------------- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/lib/models/cookie_data.dart b/lib/models/cookie_data.dart index 809aacad..9c07b14b 100644 --- a/lib/models/cookie_data.dart +++ b/lib/models/cookie_data.dart @@ -13,24 +13,27 @@ import 'package:tsdm_client/utils/debug.dart'; /// username), what we can do is save these cookies as cache in memory. /// And it's cookieProvider's work to save them to database. class CookieData implements Storage { - CookieData(this.cookieStreamSink) : _username = null; + CookieData(this.cookieStreamController) : _username = null; CookieData.withUsername({ required String username, required Map cookie, - required this.cookieStreamSink, + required this.cookieStreamController, }) : _username = username, _cookieMap = cookie; CookieData.withData({ required String username, required Map cookie, - required this.cookieStreamSink, + required this.cookieStreamController, }) : _username = username, _cookieMap = cookie; - /// Stream to send cookie event. - final StreamSink cookieStreamSink; + /// Stream of [UserCookieEvent] to receive all cookie events happened in + /// [CookieData]. + /// + /// Handle events and sync cookie to database. + StreamController? cookieStreamController; final String? _username; @@ -66,10 +69,12 @@ class CookieData implements Storage { return false; } - cookieStreamSink.add(UserCookieEvent.update( - username: _username!, - cookie: _cookieMap, - )); + if (cookieStreamController != null && cookieStreamController!.isClosed) { + cookieStreamController?.sink.add(UserCookieEvent.update( + username: _username!, + cookie: _cookieMap, + )); + } return true; } @@ -87,9 +92,11 @@ class CookieData implements Storage { } debug('CookieData $hashCode: delete cookie: $_username'); - cookieStreamSink.add(UserCookieEvent.delete( - username: _username!, - )); + if (cookieStreamController != null && !cookieStreamController!.isClosed) { + cookieStreamController?.sink.add(UserCookieEvent.delete( + username: _username!, + )); + } return true; } diff --git a/lib/providers/cookie_provider.dart b/lib/providers/cookie_provider.dart index f472e479..1477860a 100644 --- a/lib/providers/cookie_provider.dart +++ b/lib/providers/cookie_provider.dart @@ -37,26 +37,15 @@ part '../generated/providers/cookie_provider.g.dart'; class Cookie extends _$Cookie { String? _username; - /// Stream of [UserCookieEvent] to receive all cookie events happened in - /// [CookieData]. - /// - /// Handle events and sync cookie to database. - StreamController? _cookieStream; - - // To make linter happy: Bypass "unclosed instance of 'Sink'" warning - // TODO: Find a proper time to close stream when instance disposing. - void _() { - _cookieStream?.close(); - } - @override CookieData build({String? username}) { - if (_cookieStream == null) { - _cookieStream = StreamController(); - _cookieStream!.stream.listen((event) async { - await _handleCookieEvent(event); - }); - } + // ignore: close_sinks + final streamController = StreamController(); + streamController.stream.listen((event) async { + await _handleCookieEvent(event); + }); + + ref.onDispose(streamController.close); // Specified user override. if (username != null) { @@ -70,17 +59,18 @@ class Cookie extends _$Cookie { return CookieData.withUsername( username: username, cookie: cookie, - cookieStreamSink: _cookieStream!.sink, + cookieStreamController: streamController, ); } - return _buildCookieDataFromLoginUser(); + return _buildCookieDataFromLoginUser(streamController); } - CookieData _buildCookieDataFromLoginUser() { + CookieData _buildCookieDataFromLoginUser( + StreamController streamController) { final username = ref.watch(appSettingsProvider).loginUsername; if (username.isEmpty) { - return CookieData(_cookieStream!.sink); + return CookieData(streamController); } _username = username; @@ -91,13 +81,13 @@ class Cookie extends _$Cookie { debug( 'failed to init cookie: current login user username=$username not found in database', ); - return CookieData(_cookieStream!.sink); + return CookieData(streamController); } return CookieData.withData( username: _username!, cookie: Map.castFrom(databaseCookie.cookie), - cookieStreamSink: _cookieStream!.sink, + cookieStreamController: streamController, ); }