본문으로 바로가기
  1. Home
  2. Flutter/Package
  3. Flutter Riverpod All Providers (5-5) - StreamProvider

Flutter Riverpod All Providers (5-5) - StreamProvider

· 댓글개 · Dev_Whale

StreamProvider는 FutureProvider와 유사하지만 Future가 아닌 Stream을 위한 것입니다.

 

StreamProvider는 일반적으로 다음과 같은 용도로 사용됩니다:

  • Firebase 또는 웹 소켓 수신 중
  • 몇 초마다 다른 provider rebuild

Stream은 업데이트를 수신하는 방법을 자연스럽게 노출하기 때문에 StreamProvider를 사용하는 것이 가치가 낮다고 생각할 수 있습니다. 특히 스트림을 수신하는 데는 Flutter의 StreamBuilder도 잘 작동할 것이라고 생각할 수 있지만, 이는 잘못된 생각입니다.

  • StreamBuilder 대신 StreamProvider를 사용하면 많은 이점이 있습니다:
  • 다른 provider가 ref.watch를 사용하여 스트림을 수신할 수 있도록 허용합니다.
  • 로딩 및 오류 케이스가 적절히 처리되도록 보장합니다.
  • 생방송 스트림과 일반 스트림을 구분할 필요가 없습니다.
  • 스트림이 전송한 최신 값을 캐시하여 이벤트가 전송된 후 리스너가 추가되더라도 리스너가 최신 이벤트에 즉시 액세스할 수 있도록 합니다.
  • SteamProvider를 재정의하여 테스트 중에 스트림을 쉽게 모의 테스트할 수 있습니다.

사용 예시: 소켓을 사용한 실시간 채팅

StreamProvider는 다음과 같이 비디오 스트리밍, 날씨 방송 Apis 또는 라이브 채팅과 같은 비동기 데이터 스트림을 처리할 때 사용됩니다:

@riverpod
Stream<List<String>> chat(ChatRef ref) async* {
  // 소켓을 사용하여 API에 연결하고 출력을 디코딩합니다.
  final socket = await Socket.connect('my-api', 4242);
  ref.onDispose(socket.close);

  var allMessages = const <String>[];
  await for (final message in socket.map(utf8.decode)) {
    // 새 메시지가 수신되었습니다. 모든 메시지 목록에 추가해 보겠습니다.
    allMessages = [...allMessages, message];
    yield allMessages;
  }
}

그러면 UI에서 다음과 같이 실시간 스트리밍 채팅을 수신할 수 있습니다:

Widget build(BuildContext context, WidgetRef ref) {
  final liveChats = ref.watch(chatProvider);
  // FutureProvider와 마찬가지로 로딩/오류 상태를 처리하기 위해 AsyncValue.when을 사용할 수 있습니다.
  return liveChats.when(
    loading: () => const CircularProgressIndicator(),
    error: (error, stackTrace) => Text(error.toString()),
    data: (messages) {
      // 모든 메시지를 스크롤 가능한 목록 보기로 표시합니다.
      return ListView.builder(
        // 아래에서 위로 메시지 표시
        reverse: true,
        itemCount: messages.length,
        itemBuilder: (context, index) {
          final message = messages[index];
          return Text(message);
        },
      );
    },
  );
}

 

💬 댓글 개
이모티콘창 닫기
울음
안녕
감사해요
당황
피폐

이모티콘을 클릭하면 댓글창에 입력됩니다.