如何在Dart中创建StreamTransformer? 试图构建一个定制的流转换器类,但是很多例子似乎过时了,文档中发现的不是(某种类型的语言可以考虑的)类(在这里找到)。这似乎不是一种非常像飞镖的方式,而是一种更像Javascript的方式(我使用飞镖来避免)

如何在Dart中创建StreamTransformer? 试图构建一个定制的流转换器类,但是很多例子似乎过时了,文档中发现的不是(某种类型的语言可以考虑的)类(在这里找到)。这似乎不是一种非常像飞镖的方式,而是一种更像Javascript的方式(我使用飞镖来避免),stream,dart,transformer,Stream,Dart,Transformer,许多在线来源说这就是创建StreamTransformer的方式,但是在扩展它时会出现错误 class exampleStreamTransformer extends StreamTransformer { //... (This won't work) } “Implements”似乎是一种方法,同时实现所需的绑定功能: class exampleStreamTransformer implements StreamTransformer { Stream bind(Stream

许多在线来源说这就是创建StreamTransformer的方式,但是在扩展它时会出现错误

class exampleStreamTransformer extends StreamTransformer
{
  //... (This won't work)
}
“Implements”似乎是一种方法,同时实现所需的绑定功能:

class exampleStreamTransformer implements StreamTransformer
{
  Stream bind(Stream stream)
  {
    //... (Go on to return new stream, etc)
  }
}
我似乎找不到这种方式的任何示例,但我自己也做了一些尝试(这在我的IDE中被接受,但在运行时不被接受,当它尝试使用pause getter时,我得到一个null对象错误):

类示例StreamTransformer实现StreamTransformer
{
流控制器(StreamController);;
流动认购(流动认购);;
流绑定(Stream-Stream)
{
_控制器=新的StreamController(
onListen:()
{
_订阅=流。侦听((数据)
{
//转换数据。
_控制器。添加(数据);
},
onError:_controller.addError,
onDone:_controller.close,
取消者:对);//不确定我该如何通过这个?????
},
onPause:\u subscription.pause,
onResume:_subscription.resume,
onCancel:\u subscription.cancel,
同步:正确
);
返回_controller.stream;
}
}

如果希望以这种方式实现它,就像以“类型化”方式生成类一样,非常感谢您的帮助。

为什么不使用
StreamTransformer.fromHandler()

输出

data: 2
data: 4
data: 6

好的。下面是另一个工作示例:

import 'dart:async';

class DuplicateTransformer<S, T> implements StreamTransformer<S, T> {
  StreamController _controller;

  StreamSubscription _subscription;

  bool cancelOnError;

  // Original Stream
  Stream<S> _stream;

  DuplicateTransformer({bool sync: false, this.cancelOnError}) {
    _controller = new StreamController<T>(onListen: _onListen, onCancel: _onCancel, onPause: () {
      _subscription.pause();
    }, onResume: () {
      _subscription.resume();
    }, sync: sync);
  }

  DuplicateTransformer.broadcast({bool sync: false, bool this.cancelOnError}) {
    _controller = new StreamController<T>.broadcast(onListen: _onListen, onCancel: _onCancel, sync: sync);
  }

  void _onListen() {
    _subscription = _stream.listen(onData,
      onError: _controller.addError,
      onDone: _controller.close,
      cancelOnError: cancelOnError);
  }

  void _onCancel() {
    _subscription.cancel();
    _subscription = null;
  }

  /**
   * Transformation
   */

  void onData(S data) {
    _controller.add(data);
    _controller.add(data); /* DUPLICATE EXAMPLE!! REMOVE FOR YOUR OWN IMPLEMENTATION!! */
  }

  /**
   * Bind
   */

  Stream<T> bind(Stream<S> stream) {
    this._stream = stream;
    return _controller.stream;
  }
}

void main() {
  // Create StreamController
  StreamController controller = new StreamController.broadcast();
  // Transform
  Stream s = controller.stream.transform(new DuplicateTransformer.broadcast());

  s.listen((data) {
    print('data: $data');
  }).cancel();

  s.listen((data) {
    print('data2: $data');
  }).cancel();

  s.listen((data) {
    print('data3: $data');
  });

  // Simulate data

  controller.add(1);
  controller.add(2);
  controller.add(3);
}
导入'dart:async';
类DuplicateTransformer实现StreamTransformer{
流控制器(StreamController);;
流动认购(流动认购);;
布尔消除器;
//原始流
溪流;;
DuplicateTransformer({bool sync:false,this.cancelOnError}){
_控制器=新的StreamController(onListen:\u onListen,onCancel:\u onCancel,onPause:(){
_subscription.pause();
},onResume:(){
_subscription.resume();
},sync:sync);
}
DuplicateTransformer.broadcast({bool sync:false,bool this.cancelOnError}){
_控制器=新的StreamController.broadcast(onListen:_onListen,onCancel:_onCancel,sync:sync);
}
void _onListen(){
_订阅=_stream.listen(onData,
onError:_controller.addError,
onDone:_controller.close,
cancelOnError:cancelOnError);
}
void _onCancel(){
_订阅。取消();
_订阅=空;
}
/**
*转化
*/
无效onData(S数据){
_控制器。添加(数据);
_controller.add(data);/*重复示例!!为自己的实现删除*/
}
/**
*束缚
*/
流绑定(Stream-Stream){
这个。_stream=stream;
返回_controller.stream;
}
}
void main(){
//创建流控制器
StreamController=新的StreamController.broadcast();
//转化
streams=controller.Stream.transform(新的duplicateConformer.broadcast());
s、 听((数据){
打印('data:$data');
}).cancel();
s、 听((数据){
打印('data2:$data');
}).cancel();
s、 听((数据){
打印('data3:$data');
});
//模拟数据
控制器。添加(1);
控制器。添加(2);
控制器。添加(3);
}
让我补充几点:

  • 查看其他dart内部转换器的源代码时,使用
    implements
    似乎是正确的方法
  • 我为常规流和广播流实现了两个版本
  • 对于常规流,您可以直接在新的流控制器上调用cancel/pause/resumt,因为我们只能监听一次
  • 如果你使用一个广播流,我发现listen()只在没有人在听这个流的情况下被调用。onCancel的行为相同。如果最后一个订户取消其订阅,则调用onCancel。这就是为什么在这里使用相同的函数是安全的

您可以使用StreamTransformer.fromHandlers轻松创建 仅将输入事件转换为输出事件的转换器

例如:

new StreamTransformer.fromHandlers(handleData: (String event, EventSink output) {
  if (event.startsWith('data:')) {
    output.add(JSON.decode(event.substring('data:'.length)));
  } else if (event.isNotEmpty) {
    output.addError('Unexpected data from CloudBit stream: "$event"');
  }
});

如果您想使用这样的函数简单地转换值

int handleData(int data) {
  return data * 2;
}
流的使用方法

stream
  .map(handleData)
  .listen((data) {
    print('data: $data');
  });
完整示例:

import 'dart:async';

int handleData(int data) {
  return data * 2;
}

void main() {
  final controller = StreamController<int>();

  controller.stream
    .map(handleData)
    .listen((data) {
      print('data: $data');
    });

  controller.add(1);
  controller.add(2);
  controller.add(3);
}
导入'dart:async';
int handleData(int数据){
返回数据*2;
}
void main(){
最终控制器=StreamController();
控制器.stream
.地图(handleData)
.listen((数据){
打印('data:$data');
});
控制器。添加(1);
控制器。添加(2);
控制器。添加(3);
}

请参见dart.dev上的

与映射不同,转换器功能更强大,允许您保持内部状态,并随时发出值。它可以实现
map
做不到的事情,比如延迟、复制、省略一些值等等

本质上,该实现需要一个基于传入的旧流提供新流的
bind
方法,以及一个有助于在运行时进行类型检查的
cast
方法

下面是一个实现“TallyTransformer”的过于简化的示例,它将整数值流转换为求和流。例如,如果到目前为止输入流有
1,1,1,-2,0,
,则输出流将是
1,2,3,1,1,
,即将所有输入相加到这一点

用法示例:
stream.transform(TallyTransformer())

class TallyTransformer实现StreamTransformer{
StreamController _controller=StreamController();
int _sum=0;//到目前为止所有值的总和
@凌驾
流绑定(Stream-Stream){
//开始监听输入流
stream.listen((值){
_总和+=价值
stream
  .map(handleData)
  .listen((data) {
    print('data: $data');
  });
import 'dart:async';

int handleData(int data) {
  return data * 2;
}

void main() {
  final controller = StreamController<int>();

  controller.stream
    .map(handleData)
    .listen((data) {
      print('data: $data');
    });

  controller.add(1);
  controller.add(2);
  controller.add(3);
}
class TallyTransformer implements StreamTransformer {
  StreamController _controller = StreamController();
  int _sum = 0; // sum of all values so far

  @override
  Stream bind(Stream stream) {
    // start listening on input stream
    stream.listen((value) {
      _sum += value; // add the new value to sum
      _controller.add(_sum); // emit current sum to our listener
    });
    // return an output stream for our listener
    return _controller.stream;
  }

  @override
  StreamTransformer<RS, RT> cast<RS, RT>() {
    return StreamTransformer.castFrom(this);
  }
}