{"id":356,"date":"2024-05-10T16:33:43","date_gmt":"2024-05-10T08:33:43","guid":{"rendered":"https:\/\/www.ixriver.com\/?p=356"},"modified":"2024-05-10T19:43:09","modified_gmt":"2024-05-10T11:43:09","slug":"dart-stream%e7%94%a8%e6%b3%95","status":"publish","type":"post","link":"https:\/\/ixriver.com\/?p=356","title":{"rendered":"Dart Stream\u7528\u6cd5"},"content":{"rendered":"\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_65 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title \" >\u76ee\u5f55<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/ixriver.com\/?p=356\/#Stream%E5%88%9B%E5%BB%BA\" title=\"Stream\u521b\u5efa\">Stream\u521b\u5efa<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/ixriver.com\/?p=356\/#%E8%BD%AC%E6%8D%A2%E7%8E%B0%E6%9C%89%E7%9A%84Stream\" title=\"\u8f6c\u6362\u73b0\u6709\u7684Stream\">\u8f6c\u6362\u73b0\u6709\u7684Stream<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/ixriver.com\/?p=356\/#%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E5%88%9B%E5%BB%BAStream\" title=\"\u4ece\u96f6\u5f00\u59cb\u521b\u5efaStream\">\u4ece\u96f6\u5f00\u59cb\u521b\u5efaStream<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/ixriver.com\/?p=356\/#Stream%E4%BD%BF%E7%94%A8\" title=\"Stream\u4f7f\u7528\">Stream\u4f7f\u7528<\/a><\/li><\/ul><\/nav><\/div>\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Stream%E5%88%9B%E5%BB%BA\"><\/span>Stream\u521b\u5efa<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"%E8%BD%AC%E6%8D%A2%E7%8E%B0%E6%9C%89%E7%9A%84Stream\"><\/span>\u8f6c\u6362\u73b0\u6709\u7684Stream<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/\/ Splits a stream of consecutive strings into lines.\n\/\/\/\n\/\/\/ The input string is provided in smaller chunks through\n\/\/\/ the `source` stream.\nStream&lt;String> lines(Stream&lt;String> source) async* {\n  \/\/ Stores any partial line from the previous chunk.\n  var partial = '';\n  \/\/ Wait until a new chunk is available, then process it.\n  await for (final chunk in source) {\n    var lines = chunk.split('\\n');\n    lines&#91;0] = partial + lines&#91;0]; \/\/ Prepend partial line.\n    partial = lines.removeLast(); \/\/ Remove new partial line.\n    for (final line in lines) {\n      yield line; \/\/ Add lines to output stream.\n    }\n  }\n  \/\/ Add final partial line to output stream, if any.\n  if (partial.isNotEmpty) yield partial;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"%E4%BB%8E%E9%9B%B6%E5%BC%80%E5%A7%8B%E5%88%9B%E5%BB%BAStream\"><\/span>\u4ece\u96f6\u5f00\u59cb\u521b\u5efaStream<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Stream&lt;int> timedCounter(Duration interval, &#91;int? maxCount]) async* {\n  int i = 0;\n  while (true) {\n    await Future.delayed(interval);\n    yield i++;\n    if (i == maxCount) break;\n  }\n}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ NOTE: This implementation is FLAWED!\n\/\/ It starts before it has subscribers, and it doesn't implement pause.\nStream&lt;int> timedCounterController(Duration interval, &#91;int? maxCount]) {\n  int counter = 0;\n  Timer? timer;\n  late StreamController&lt;int> controller;\n\n  void tick(Timer timer) {\n    counter++;\n    controller.add(counter);\n    print('yield $counter'); \/\/ Ask stream to send counter values as event.\n    if (maxCount != null &amp;&amp; counter >= maxCount) {\n      timer.cancel();\n      controller.close(); \/\/ Ask stream to shut down and tell listeners.\n    }\n  }\n\n  void startTimer() {\n    timer = Timer.periodic(\n        interval, tick); \/\/ BAD: Starts before it has subscribers.\n  }\n\n  void stopTimer() {\n    timer?.cancel();\n    timer = null;\n  }\n\n  controller = StreamController&lt;int>(\n      onListen: startTimer,\n      onPause: stopTimer,\n      onResume: startTimer,\n      onCancel: stopTimer);\n\n  return controller.stream;\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Stream%E4%BD%BF%E7%94%A8\"><\/span>Stream\u4f7f\u7528<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>void useTimedCounterController() async {\n  final st = timedCounterController(const Duration(seconds: 1), 100);\n  await Future.delayed(const Duration(seconds: 10));\n  print('start listen');\n  late StreamSubscription&lt;int> subscription;\n  subscription = st.listen((event) {\n    print('listen $event');\n    if (event == 5) {\n      subscription.pause(Future.delayed(const Duration(seconds: 5)));\n    }\n  });\n}\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Future&lt;int> useTimedCounterBasic() async {\n  final st = timedCounter(const Duration(seconds: 1), 10);\n  var sum = 0;\n  try {\n    await for (final value in st) {\n      sum += value;\n    }\n  } catch (e) {\n    print('catch $e');\n  } finally {\n    print('sum is $sum');\n  }\n  return sum;\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Stream\u521b\u5efa \u8f6c\u6362\u73b0\u6709\u7684Stream \u4ece\u96f6\u5f00\u59cb\u521b\u5efaStream Stream\u4f7f\u7528<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[],"blocksy_meta":[],"featured_image_urls":{"full":"","thumbnail":"","medium":"","medium_large":"","large":"","1536x1536":"","2048x2048":""},"post_excerpt_stackable":"<p>\u76ee\u5f55 Toggle Stream\u521b\u5efa\u8f6c\u6362\u73b0\u6709\u7684Stream\u4ece\u96f6\u5f00\u59cb\u521b\u5efaStreamStream\u4f7f\u7528 Stream\u521b\u5efa \u8f6c\u6362\u73b0\u6709\u7684Stream \/\/\/ Splits a stream of consec&hellip;<\/p>\n","category_list":"<a href=\"https:\/\/ixriver.com\/?cat=20\" rel=\"category\">Flutter<\/a>","author_info":{"name":"admin","url":"https:\/\/ixriver.com\/?author=1"},"comments_num":"0 comments","_links":{"self":[{"href":"https:\/\/ixriver.com\/index.php?rest_route=\/wp\/v2\/posts\/356"}],"collection":[{"href":"https:\/\/ixriver.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ixriver.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ixriver.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ixriver.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=356"}],"version-history":[{"count":5,"href":"https:\/\/ixriver.com\/index.php?rest_route=\/wp\/v2\/posts\/356\/revisions"}],"predecessor-version":[{"id":363,"href":"https:\/\/ixriver.com\/index.php?rest_route=\/wp\/v2\/posts\/356\/revisions\/363"}],"wp:attachment":[{"href":"https:\/\/ixriver.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ixriver.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ixriver.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}