如何取消 Cubit 内的 StreamSubscription?

问题描述

我有一个 cubit 来监听消息流,并发出一个保存消息的状态。 在屏幕中,我使用 BlocProvider 来访问肘,并使用 BlocBuilder 来显示 消息。

在下面的例子中,我是否需要关闭在 listen() 上创建的 StreamSubscription?有没有干净的方法来做到这一点?

class MessageCubit extends Cubit<MessageState> {
  final GetMessagesUseCase getMessagesUseCase;
  MessageCubit({this.getMessagesUseCase}) : super(MessageInitial());
  Future<void> getMessages({String senderId,String recipientId}) async {
    emit(MessageLoading());
    try {
      final messagesstreamData = getMessagesUseCase.call();

      //This is where I listen to a stream
      messagesstreamData.listen((messages) {
        emit(MessageLoaded(messages: messages));
      });


    } on SocketException catch (_) {
      emit(MessageFailure());
    } catch (_) {
      emit(MessageFailure());
    }
  }
}

解决方法

您不需要需要关闭订阅,但您应该作为避免潜在内存泄漏的好习惯。既然如此简单,就没有任何牺牲。

  1. 创建一个 StreamSubscription<your type> 类型的类变量。假设它名为 sub
  2. 在听之前在 getMessages 中:await sub?.cancel()
  3. 然后sub = messagesStreamData.listen(...
  4. 覆盖 Cubit 的 close 方法并运行与第 2 项中相同的命令。

完整代码:

class MessageCubit extends Cubit<MessageState> {
  final GetMessagesUseCase getMessagesUseCase;

  // Added
  StreamSubscription<YOUR_MESSAGES_TYPE> sub;

  MessageCubit({this.getMessagesUseCase}) : super(MessageInitial());
  Future<void> getMessages({String senderId,String recipientId}) async {
    emit(MessageLoading());
    try {
      final messagesStreamData = getMessagesUseCase.call();

      // Added
      await sub?.cancel();
      //This is where I listen to a stream
      sub = messagesStreamData.listen((messages) {
        emit(MessageLoaded(messages: messages));
      });


    } on SocketException catch (_) {
      emit(MessageFailure());
    } catch (_) {
      emit(MessageFailure());
    }
  }

  // Added    
  @override
  Future<void> close() async {
    await sub?.cancel();
    return super.close();
  }
}