LoginSignup
7
4

More than 3 years have passed since last update.

【Flutter】バグ解決: Bad state: Stream has already been listened to.

Last updated at Posted at 2020-03-29

今回の件のGitHubはこちら

現象

StreamControllerを使ってBLoCパターンでstatement管理をしていたが、TabBarViewを追加して、
Tabを切り替えて、再度同じタブに復帰した際に画面の表示が崩れるようになりました。

その際のerrorがこちら。

Bad state: Stream has already been listened to.

解決策

StreamControllerではなく、BehaviorSubjectを使用することで解消

元のソースコード

エラー解消前
import 'dart:async';

class CounterBloc {
  // input
  final _actionController = StreamController<bool>();
  Sink<void> get changeCountAction => _actionController.sink;

  //output
  final _countController = StreamController<int>();
  Stream<int> get count => _countController.stream;

  int _count = 0;

  CounterBloc() {
    _actionController.stream.listen((isPlus) {
      if (isPlus) {
        _count++;
      } else {
        _count--;
      }
      _countController.sink.add(_count);
    });
  }

  void dispose() {
    _actionController.close();
    _countController.close();
  }
}
エラー解消後
import 'dart:async';
import 'package:rxdart/rxdart.dart';

class CounterBloc {
  // input
  final _actionController = BehaviorSubject<bool>();
  Sink<void> get changeCountAction => _actionController.sink;

  //output
  final _countController = BehaviorSubject<int>();
  Stream<int> get count => _countController.stream;

  int _count = 0;

  CounterBloc() {
    _actionController.stream.listen((isPlus) {
      if (isPlus) {
        _count++;
      } else {
        _count--;
      }
      _countController.sink.add(_count);
    });
  }

  void dispose() {
    _actionController.close();
    _countController.close();
  }
}

その他

勉強不足でStreamControllerBehaviorSubjectの違いをまだ理解できておりません。
ご存知の方いましたら、教えていただけますと幸甚です。

@ntaooさんより、メッセージいただきました。

StreamController: StreamのController。
デフォルトではSingle Subscription Streamなので、一度listenしたあともう一度listenするとそのエラーが発生します。

BehaviorSubject: Broadcast Stream Controller に、Stream Elementのcacheという振る舞いを追加したもの。
Broadcast Stream Controllerが制御するStreamは何度でもlistenできますがlistenerリソースの管理をしないとリソースリークする可能性があります。
ListenしたタイミングでBehaviorSubjectから最新のcacheがlistenerに流れてきます。

参考記事

7
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4