Flutter多线程处理插件dart_thread的使用

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

Flutter多线程处理插件 dart_thread 的使用

dart_thread 是一个经典的线程实现库,类似于 Delphi 中的 TThread。它易于使用,并且在所有平台上使用相同的代码(在桌面端映射到 Isolates,在 Web 端映射到 Workers)。

特性

  • DartThread 类包含 onExecute 方法,在线程启动时执行。
  • onGetMessage 方法在主线程发送消息时触发。
  • DartThread 也可以向主线程发送消息。
  • 在 Web 平台上,从主线程发送变量给 Worker 时有严格的限制:JS 只允许发送基本类型,而不支持自定义类和其他结构。因此,DartThread 提供了 messageToObject 方法来实现自定义变量的打包和解包。

使用示例

示例代码

以下是一个完整的示例,展示了如何使用 dart_thread 插件:

import 'dart:math';
import 'package:dart_thread/dart_thread.dart';

class TestThread extends DartThread {
  // 需要将类映射到 super.init,
  // 因为 Dart 不允许覆盖静态方法
  static TestThread newInstance() => TestThread();

  @override
  Future<void> onExecute(Function(dynamic message) sendMessage) async {
    while (true) {
      sendMessage(Random().nextInt(100));
      await Future.delayed(Duration(seconds: 1));
    }
  }

  @override
  Future<void> onGetMessage(message, Function(dynamic message) sendMessage) async {
    sendMessage(message);
  }
}

void main() async {
  TestThread testThread = TestThread();

  await testThread.init(TestThread.newInstance, (message) {
    // 接收来自 Isolate 或 Worker 的消息
    print('Received from thread: $message');
  });

  // 发送消息到 Isolate 或 Worker
  testThread.sendMessage('echo');

  await Future.delayed(Duration(seconds: 10));

  testThread.deInit();
}

自定义类的传递

在 Web 平台上,需要将自定义类转换为 JSON 格式进行传输。以下是如何实现这一功能的示例:

class CustomClass {
  final int i;
  final String s;
  final double d;

  CustomClass(this.i, this.s, this.d);

  Map<String, dynamic> toJson() => {
        'runtimeType': 'CustomClass',
        'i': i,
        's': s,
        'd': d,
      };

  CustomClass.fromJson(Map<String, dynamic> json)
      : i = json['i'],
        s = json['s'],
        d = json['d'];

  @override
  String toString() {
    return '$i, $s, $d';
  }
}

class TestThread extends DartThread {
  @override
  Future<void> onExecute(Function(dynamic message) sendMessage) async {
    int counter = 0;
    while (true) {
      sendMessage(++counter);
      await Future.delayed(Duration(seconds: 1));
    }
  }

  @override
  Future<void> onGetMessage(
      message, Function(dynamic message) sendMessage) async {
    print('Receive message from main thread: $message');
    sendMessage(message);
  }

  @override
  dynamic messageToObject(message) {
    if (message is Map<String, dynamic>) {
      if (message['runtimeType'] == 'CustomClass')
        return CustomClass.fromJson(message);
    }
    return super.messageToObject(message);
  }
}

void main() async {
  TestThread testThread1 = TestThread();
  TestThread testThread2 = TestThread();

  await testThread1.init(TestThread.newInstance, (message) {
    print('Receive message from testThread1: $message');
  });

  await testThread2.init(TestThread.newInstance, (message) {
    print('Receive message from testThread2: $message');
  });

  testThread1.sendMessage('echo');
  testThread2.sendMessage('echo');

  CustomClass customClass = CustomClass(1, '1', 1.0);
  testThread1.sendMessage(customClass);
  testThread2.sendMessage(customClass);

  await Future.delayed(Duration(seconds: 10));

  testThread1.deInit();
  testThread2.deInit();
}

准备 Web Worker

为了在 Web 平台上使用 dart_thread,你需要创建一个 Web Worker 的 Dart 文件,并将其编译为 JavaScript 文件。以下是步骤:

  1. 创建名为 TestThread.dart 的 Web Worker Dart 文件:

    @JS()
    
    import 'dart:html';
    import 'dart:js_interop';
    import 'main.dart';
    
    @JS('self')
    external JSObject get _self;
    DedicatedWorkerGlobalScope get self => _self as DedicatedWorkerGlobalScope;
    
    void main() async {
      await TestThread().main(self);
    }
    
  2. 使用命令行在项目中的 web 文件夹下编译 Dart 文件为 JavaScript 文件:

    set "dart_path=D:\sdk\flutter\bin\cache\dart-sdk\bin"
    set "flutter_web_sdk=D:\sdk\flutter\bin\cache\flutter_web_sdk"
    
    call "%dart_path%\dart" compile js -O2 --libraries-spec="%flutter_web_sdk"\libraries.json -o web/TestThread.dart.js lib/TestThread.dart || pause
    

更多关于Flutter多线程处理插件dart_thread的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter多线程处理插件dart_thread的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中使用dart_thread插件来实现多线程处理是一个有效的方法,特别是当你需要在后台执行耗时任务而不阻塞UI线程时。以下是一个简单的代码示例,展示了如何使用dart_thread来创建和管理线程。

首先,确保你已经在pubspec.yaml文件中添加了dart_thread的依赖:

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

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

接下来是一个完整的Flutter应用示例,展示了如何使用dart_thread进行多线程处理:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Multi-threading Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

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

class _MyHomePageState extends State<MyHomePage> {
  String _result = 'Loading...';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Multi-threading Example'),
      ),
      body: Center(
        child: Text(
          _result,
          style: TextStyle(fontSize: 24),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _startLongRunningTask,
        tooltip: 'Start Task',
        child: Icon(Icons.play_arrow),
      ),
    );
  }

  void _startLongRunningTask() {
    // 使用DartThread来启动一个新线程
    DartThread thread = DartThread(() {
      // 模拟耗时任务
      DartThread.sleep(5000); // 休眠5秒
      String result = "Task Completed!";

      // 使用DartThread.post将结果发送回UI线程
      DartThread.post(() {
        setState(() {
          _result = result;
        });
      });
    });

    // 启动线程
    thread.start();
  }
}

在这个示例中,我们创建了一个简单的Flutter应用,其中包含一个文本显示区域和一个浮动操作按钮。点击按钮时,会启动一个新线程来执行耗时任务(这里使用DartThread.sleep(5000)来模拟耗时操作)。任务完成后,结果会通过DartThread.post方法发送回UI线程,并更新UI。

注意:

  1. DartThread的API设计使得线程间通信相对简单,通过DartThread.post方法可以将任务发送回UI线程进行UI更新。
  2. 由于Dart是单线程的(除了Isolate),dart_thread插件实际上是通过Isolate机制来实现多线程的。因此,虽然它提供了一个更直观的线程接口,但背后还是依赖于Dart的Isolate机制。

确保在实际应用中根据需求合理使用多线程,以避免不必要的复杂性和性能开销。

回到顶部