Stream.listen 在 web 上完全重启 Flutter 后幸存下来
Posted
技术标签:
【中文标题】Stream.listen 在 web 上完全重启 Flutter 后幸存下来【英文标题】:Stream.listen survives full restart of flutter on web 【发布时间】:2021-12-28 02:11:17 【问题描述】:Stream.listen() 似乎可以在网络上完全重启,有时也可以在移动设备上幸存下来。
main.dart
import 'package:flutter/material.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'dart:convert';
import 'dart:math';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context) => MaterialApp(home: MyHomePage());
class MyHomePage extends StatefulWidget
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
var test = 0;
late int randomInt;
var random = Random();
var uri = Uri.parse('wss://ws-feed-public.sandbox.pro.coinbase.com');
late WebSocketChannel channel;
String request = json.encode(
"type": "subscribe",
"product_ids": ["BTC-USD"],
"channels": ["heartbeat"],
);
@override
void initState()
randomInt = random.nextInt(1000);
channel = WebSocketChannel.connect(uri);
channel.sink.add(request);
channel.stream.listen((event)
print('$randomInt: $test');
test = test + 1;
);
super.initState();
@override
Widget build(BuildContext context) => Container();
pubspec.yaml
name: echowebsocket
description: A new Flutter project.
version: 1.0.0+1
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
web_socket_channel: ^2.1.0
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
当我在 Flutter Web 中运行上述代码并进行热重启(android studio 中的绿色播放按钮)时,流 .listen() 函数在重启后仍然存在,两个监听函数仍在运行。 冷运行后的示例输出(Chrome 关闭):
This application is not configured to build on the web.
To add web support to a project, run `flutter create .`.
Launching lib/main.dart on Chrome in debug mode...
Waiting for connection from debug service on Chrome...
This app is linked to the debug service: ws://127.0.0.1:56738/yLBcQjxMep4=/ws
Debug service listening on ws://127.0.0.1:56738/yLBcQjxMep4=/ws
???? Running with sound null safety ????
Debug service listening on ws://127.0.0.1:56738/yLBcQjxMep4=/ws
582: 0
582: 1
582: 2
582: 3
582: 4
582: 5
582: 6
582: 7
582: 8
然后在热重启之后:
Performing hot restart...
Waiting for connection from debug service on Chrome...
582: 30
Restarted application in 155ms.
876: 0
876: 1
582: 31
876: 2
582: 32
876: 3
582: 33
582: 34
876: 4
582: 35
876: 5
582: 36
876: 6
582: 37
876: 7
876: 8
如您所见,现在执行了两个监听函数。我的印象是,任何状态都不应该在热重启后幸存下来。我有时能够在模拟器上重新创建这个问题,但它似乎每次都在网络上工作。这是颤振医生的输出:
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.5.2, on macOS 11.6 20G165 darwin-x64, locale en)
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
✗ cmdline-tools component is missing
Run `path/to/sdkmanager --install "cmdline-tools;latest"`
See https://developer.android.com/studio/command-line for more details.
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for ios and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] Connected device (1 available)
! Doctor found issues in 1 category.
【问题讨论】:
【参考方案1】:您遇到的是内存/资源泄漏。完成后,您需要覆盖关闭WebSocketChannel
。
@override
void dispose()
channel.sink.close();
super.dispose();
更新 问题是由于热重启在 Chrome 上的工作方式。请在 GitHub 上查看 issue。
【讨论】:
当我添加该代码时,我得到了相同的行为。当您进行热重启时,似乎没有调用 dispose() 。但我认为这无关紧要,因为当您进行热重启时,一切都会消失。 热重启不能简单地擦除所有内容。您必须确保根据需要释放资源。但是,当您进行热重启时会调用dispose()
,这通常是您应该释放资源的地方。我刚刚尝试了您的代码,只添加了我的建议,并且它有效。您可能会在记忆中看到以前 Web 套接字通道的残余。作为内存泄漏,您将无法通过代码删除它们并重新启动。尝试重启设备。
我重新启动了我的整个计算机,然后再次尝试,仍然是相同的行为。您是否在 chrome 中尝试过?
抱歉,我没有看到问题出在 Chrome 上。问题确实是热重载在 Chrome 上的工作方式。它会立即杀死页面,从而杀死应用程序,而不会释放资源。请在 GitHub 上查看 issue。您可能希望使用该线程中讨论的几种解决方法。不过,请务必始终关闭 dispose
中的流。
啊,就是这样。感谢您的帮助。以上是关于Stream.listen 在 web 上完全重启 Flutter 后幸存下来的主要内容,如果未能解决你的问题,请参考以下文章