Flutter数据流隔离插件stream_isolate的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter数据流隔离插件stream_isolate的使用

API Reference

基本使用

要使用StreamIsolate,可以调用StreamIsolate.spawn,并传入与Isolate.spawn相同的参数。然后可以使用返回的实例订阅由子线程发布的的事件。

final streamIsolate = await StreamIsolate.spawn(doWork);
await for (final i in streamIsolate.stream) {
  print(i);
}
Stream<int> doWork() async* {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
}

双向通信

也可以调用BidirectionalStreamIsolate.spawn(或StreamIsolate.spawnBidirectional)来创建一个暴露额外通信流以发送消息到实例的子线程:

final streamIsolate = await BidirectionalStreamIsolate.spawn(doWork);
await for (final i in streamIsolate.stream) {
  print(i);
  streamIsolate.send('received');
}
Stream<int> doWorkWithListener(Stream<String> inc) async* {
  inc.listen((msg) => print('from main: $msg'));

  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
}

传递初始参数

可以可选地发送一个参数,在子线程首次运行时将其传递给函数。这通过StreamIsolate.spawnWithArgumentBidirectionalStreamIsolate.spawnWithArgument方法实现。

class IsolateArgs {
  final int index;
  final String name;

  const IsolateArgs(this.index, this.name);
}

...

final args = IsolateArgs(1, 'Worker Isolate 1');
final streamIsolate = await StreamIsolate.spawnWithArgument(doWork, argument: args);
await for (final i in streamIsolate.stream) {
  print(i);
  streamIsolate.send('received');
}
Stream<int> doWorkWithListener(Stream<String> inc, IsolateArgs args) async* {
  print('Starting worker isolate ${args.name}, Index: ${args.index}');

  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
}

示例

  • Vanilla - 一个简单的使用流隔离的示例。
  • RxDart - 使用RxDart管理隔离流的一个示例。
  • Multithreaded Noise - 一个使用流隔离的Flutter应用,用于生成动画Perlin Noise。

示例代码

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Stream Isolate Example')),
        body: StreamIsolateExample(),
      ),
    );
  }
}

class StreamIsolateExample extends StatefulWidget {
  [@override](/user/override)
  _StreamIsolateExampleState createState() => _StreamIsolateExampleState();
}

class _StreamIsolateExampleState extends State<StreamIsolateExample> {
  final Stream<int> _isolateStream = Stream<int>.empty();

  void _startIsolate() async {
    try {
      final isolate = await StreamIsolate.spawn(() {
        var count = 0;
        while (true) {
          setState(() {
            _isolateStream.add(count++);
          });
        }
      });

      // 订阅子线程发布的内容
      isolate.stream.listen((value) {
        print('Received from isolate: $value');
      });
    } catch (e) {
      print('Error starting isolate: $e');
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Center(
      child: ElevatedButton(
        onPressed: _startIsolate,
        child: Text('Start Isolate'),
      ),
    );
  }
}

更多关于Flutter数据流隔离插件stream_isolate的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据流隔离插件stream_isolate的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter应用中使用stream_isolate插件来实现数据流隔离的示例代码。stream_isolate插件允许你在Flutter应用中创建隔离区(Isolate),并在主UI线程和隔离区之间安全地传递数据流。这对于执行耗时操作而不阻塞UI线程非常有用。

首先,你需要在你的pubspec.yaml文件中添加stream_isolate依赖:

dependencies:
  flutter:
    sdk: flutter
  stream_isolate: ^x.y.z  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来,我们来看一个具体的代码示例:

main.dart

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final StreamIsolate<int> _streamIsolate = StreamIsolate<int>();
  String _result = 'No result yet';

  @override
  void initState() {
    super.initState();
    // 监听来自Isolate的数据流
    _streamIsolate.listen((data) {
      setState(() {
        _result = 'Result from isolate: $data';
      });
    });

    // 启动Isolate并发送数据
    _startIsolate();
  }

  void _startIsolate() async {
    // 调用Isolate中的计算函数
    await _streamIsolate.spawn(calculateNumbers);

    // 向Isolate发送数据
    for (int i = 1; i <= 10; i++) {
      _streamIsolate.send(i);
    }

    // 关闭Isolate
    _streamIsolate.close();
  }

  static Future<void> calculateNumbers(StreamIsolateReceiver<int, int> receiver) async {
    receiver.stream.listen((int data) async {
      // 模拟耗时操作
      await Future.delayed(Duration(seconds: 1));
      int result = data * data; // 例如,计算平方
      receiver.send(result); // 将结果发送回主线程
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Stream Isolate Example'),
      ),
      body: Center(
        child: Text(_result),
      ),
    );
  }
}

解释

  1. 依赖添加:首先,在pubspec.yaml文件中添加stream_isolate依赖。

  2. StreamIsolate实例:在_MyHomePageState类中,创建一个StreamIsolate<int>实例。这个实例用于在UI线程和Isolate之间传递整数数据。

  3. 监听数据流:使用_streamIsolate.listen方法来监听来自Isolate的数据流。每当Isolate发送数据时,UI线程会更新显示结果。

  4. 启动Isolate:在_startIsolate方法中,调用_streamIsolate.spawn方法来启动Isolate并指定要在Isolate中运行的函数calculateNumbers。然后,向Isolate发送一系列整数数据。

  5. Isolate中的计算calculateNumbers函数接收一个StreamIsolateReceiver<int, int>参数,用于接收主线程发送的数据并发送结果回主线程。在这个函数中,我们模拟了一个耗时操作(使用Future.delayed),然后计算数据的平方,并将结果发送回主线程。

  6. UI更新:每当从Isolate接收到数据时,_streamIsolate.listen中的回调会被触发,更新UI显示的结果。

  7. 关闭Isolate:在发送完所有数据后,调用_streamIsolate.close方法来关闭Isolate。

这个示例展示了如何使用stream_isolate插件在Flutter应用中实现数据流隔离,从而避免耗时操作阻塞UI线程。你可以根据需要修改这个示例来处理不同类型的数据和执行不同的计算。

回到顶部