Stream

import 'dart:async';

/*
  스트림은 무엇입니까?
  스트림은 파이프이다. 해당 파이프에는 여러가지 데이터가 들어올 수 있다.
  데이터가 파이프의 입구에서 들어왔다가 출구로 빠져나간다.
*/

/*
  스트림에 의해 전달 될 수있는 것은 무엇입니까?
  값, 이벤트, 객체, 컬렉션, 맵, 오류 또는 심지어 다른 스트림에서 
  모든 유형의 데이터가 스트림에 의해 전달 될 수 있습니다.
*/

/*
  async* 게으른 연산 : 요청이 있을 때는 연산을 미루다가 for문에서 사용할 때
  연산을 한다.

  yield : return과 비슷하게 값을 반환해주는데 한번에 하나씩 return함과 동시에
  함수가 종료되지 않고 계속 열려있으면서 지속적으로 return을 해주고 소비가 끝나면 종료된다.
*/

Stream<int> download() async* {
  print("countStream");
  
  for (int i = 1; i <= 10; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

main() async {
  var stream = download(); //실행안됨.왜냐면 게으르니까!!
  
  /*
    이때 stream이 만들어짐. 사용할 때!!
    stream에 데이터가 1,2,3,4,5,6,7,8,9,10 이렇게 들어가 있음.
  */
  print("stream 소비 시작");
  await for (var value in stream) {
    print(value);
  }
}

StreamController

import 'dart:async';

Stream<int> download() async* {
  print("download");

  for (int i = 1; i <= 2; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}

main() async {
  var controller = StreamController<int>(); // StreamController 생성
  controller.addStream(download());
  
  // 10초후에 값 추가됨
  Future.delayed(Duration(seconds: 10), (){
    controller.add(5000);
    print("stream에 5000 추가됨");
  });
  
  // stream에 있는 값을 수신하여 결과 출력 (1, 2) -> 추가될때 5000 갱신
  await for (var value in controller.stream) {
    print(value);
  }

}

StreamBuilder in Flutter


StreamProvider in Flutter Riverpod

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

Stream<String> say() async* {
  for (var i = 0; i < 2; i++) {
    await Future.delayed(Duration(seconds: 2));
    yield 'Say $i times';
  }
}

final streamController = StreamController<String>();
final helloStreamProvider = StreamProvider.autoDispose<String>((ref) {
  streamController.addStream(say());
  return streamController.stream;
});

void main() {
  runApp(
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends ConsumerWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final helloData = ref.watch(helloStreamProvider);
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: helloData.when(
            data: (data) {
              print("데이터 들어옴");
              return buildText(data);
            },
            error: (error, stackTrace) => buildText("Error"),
            loading: () => buildText("No Data"),
          ),
        ),
        floatingActionButton: FloatingActionButton(
            onPressed: () {
              streamController.add("end");
            },
            child: Text("add")),
      ),
    );
  }

  Text buildText(String content) {
    return Text(
      content,
      style: const TextStyle(
        fontSize: 100,
      ),
    );
  }
}

StreamProvider And Riverpod And WebSocket 서버

https://github.com/codingspecialist/springboot-websocket-with-flutter