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 后幸存下来的主要内容,如果未能解决你的问题,请参考以下文章

JDK扩展DCEVM让WEB程序完全不重启调试

Btrace入门到熟练小工完全指南

solr管理集合

调试时 Flutter VS Code 中的热重启(以前是完全重启)

创建一个观看列表的流?

jenkins中重启tomcat失败操作