Flutter原生信号量管理插件runtime_native_semaphores的使用

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

Flutter原生信号量管理插件runtime_native_semaphores的使用

概述

runtime_native_semaphores 包提供了一个Dart接口,用于利用本地信号量机制,允许跨进程和跨隔离区同步。这个包在多个Dart隔离区或甚至单独的进程(如AOT)需要协调访问共享资源的情况下特别有用。通过利用操作系统本地信号量,runtime_native_semaphores 确保同步既稳健又高效。

使用场景

  • 跨隔离区同步:使用命名信号量来同步和协调不同Dart隔离区内的原子操作,例如数据库写入、文件访问或其他共享资源。
  • 跨进程线程同步:在跨越多个进程的应用程序中,命名信号量可以确保一次只有一个进程访问关键资源/代码段,防止竞争条件并确保数据完整性。

平台支持

runtime_native_semaphores 包支持以下平台:

  • MacOS (x86_64, arm64)
  • Linux (x86_64, arm64)
  • Windows (x86_64)

安装

要在您的Dart项目中添加 runtime_native_semaphores,请在 pubspec.yaml 文件中包含它:

dependencies:
  runtime_native_semaphores: ^0.0.3

开始使用

runtime_native_semaphores 包提供了一个统一的API,在不同的MacOS、Linux和Windows平台上处理命名信号量。该包公开了一个 NativeSemaphore 类,可用于创建、打开、锁定、解锁、管理和处置命名信号量。

创建一个命名信号量

下面的例子展示了如何在不同的Dart隔离区中创建、锁定和解锁信号量。这对于资源在隔离区或进程之间共享的场景非常有用。

import 'dart:isolate';
import 'package:runtime_native_semaphores/runtime_native_semaphores.dart' show NativeSemaphore;
import 'dart:math';

void main() {
  // 创建一个唯一的标识符用于信号量 
  final String name = 'my-native-named-semaphore-identifier';
  
  spawnIsolate(name, 1);
  spawnIsolate(name, 2);
  // 根据需要添加更多隔离区
}

Future<void> spawnIsolate(String name, int isolate) async {
  void isolateEntryPoint(SendPort sendPort) {
    final sem = NativeSemaphore(identifier: name);
    
    if (!sem.lock()) {  // 尝试锁定信号量
      throw Exception("Failed to lock semaphore in isolate $isolate");
    }
    
    // 在这里执行工作...例如随机阻塞操作
    sleep(Duration(milliseconds: Random().nextInt(500)));
    
    if (!sem.unlock()) {  // 解锁信号量
      throw Exception("Failed to unlock semaphore in isolate $isolate");
    }
    
    sendPort.send(true);  // 发送完成信号
  }

  final receivePort = ReceivePort();
  await Isolate.spawn(isolateEntryPoint, receivePort.sendPort);
  await receivePort.first;
  //...
  
  // 清理资源
  sem.dispose();  // 处置信号量
  receivePort.close();  // 关闭接收端口
}

更多关于Flutter原生信号量管理插件runtime_native_semaphores的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter原生信号量管理插件runtime_native_semaphores的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter原生信号量管理插件runtime_native_semaphores的使用,下面是一个具体的代码案例,展示了如何在Flutter应用中集成并使用该插件。

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

dependencies:
  flutter:
    sdk: flutter
  runtime_native_semaphores: ^latest_version  # 替换为最新版本号

然后,运行flutter pub get来获取依赖。

接下来,在Flutter项目中创建一个原生通道来与原生代码进行通信,并管理信号量。这里假设你已经有了一些原生开发的知识,特别是在iOS和Android平台上。

Flutter Dart 代码

创建一个Dart文件,例如semaphore_service.dart,用于封装与原生代码交互的逻辑:

import 'dart:async';
import 'package:flutter/services.dart';
import 'package:runtime_native_semaphores/runtime_native_semaphores.dart';

class SemaphoreService {
  static const MethodChannel _channel = MethodChannel('com.example.app/semaphores');

  // 初始化信号量
  Future<void> initSemaphore(int initialCount) async {
    try {
      await _channel.invokeMethod('initSemaphore', initialCount);
    } on PlatformException catch (e) {
      print("Failed to initialize semaphore: '${e.message}'.");
    }
  }

  // 等待信号量
  Future<void> waitSemaphore() async {
    try {
      await _channel.invokeMethod('waitSemaphore');
    } on PlatformException catch (e) {
      print("Failed to wait on semaphore: '${e.message}'.");
    }
  }

  // 释放信号量
  Future<void> postSemaphore() async {
    try {
      await _channel.invokeMethod('postSemaphore');
    } on PlatformException catch (e) {
      print("Failed to post semaphore: '${e.message}'.");
    }
  }
}

原生代码

iOS (Swift)

ios/Runner/AppDelegate.swift中添加对插件通道的处理:

import UIKit
import Flutter
import runtime_native_semaphores  // 确保你已经通过CocoaPods导入了插件

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

class SemaphoreHandler: NSObject, FlutterMethodChannelDelegate {
  private var semaphore: DispatchSemaphore?

  func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
    switch call.method {
    case "initSemaphore":
      guard let initialCount = call.arguments as? Int else {
        result(FlutterError(code: "Invalid argument", message: "Expected an integer value for initialCount", details: nil))
        return
      }
      semaphore = DispatchSemaphore(value: initialCount)
      result(success: true)
    case "waitSemaphore":
      semaphore?.wait()
      result(success: true)
    case "postSemaphore":
      semaphore?.signal()
      result(success: true)
    default:
      result(FlutterError(code: "Unimplemented", message: "Method '\(call.method)' not implemented.", details: nil))
    }
  }
}

// 在AppDelegate中注册MethodChannel
let semaphoreChannel = FlutterMethodChannel(name: "com.example.app/semaphores", binaryMessenger: registrar(forPlugin: "runtime_native_semaphores")!.messenger())
let semaphoreHandler = SemaphoreHandler()
semaphoreChannel.setMethodCallHandler(semaphoreHandler)

Android (Kotlin)

android/app/src/main/kotlin/.../MainActivity.kt中添加对插件通道的处理:

package com.example.app

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
    private val CHANNEL = "com.example.app/semaphores"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "initSemaphore" -> {
                    val initialCount = call.argument<Int>("initialCount") ?: 0
                    val semaphore = java.util.concurrent.Semaphore(initialCount)
                    // 在这里保存semaphore引用,可能需要一个全局变量或适当的存储机制
                    result.success(true)
                }
                "waitSemaphore" -> {
                    // 获取之前保存的semaphore引用并调用wait()
                    // semaphore.acquire() // 示例代码,实际使用时需要确保semaphore是可访问的
                    result.success(true)
                }
                "postSemaphore" -> {
                    // 获取之前保存的semaphore引用并调用release()
                    // semaphore.release() // 示例代码,实际使用时需要确保semaphore是可访问的
                    result.success(true)
                }
                else -> result.notImplemented()
            }
        }
    }
}

注意:在Android部分,由于Kotlin代码示例中的信号量管理需要全局或持久化存储,这里简化为注释。实际使用中,你可能需要设计一个合适的数据结构来管理信号量的生命周期。

使用示例

在你的Flutter组件或页面中,可以这样使用SemaphoreService

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

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    SemaphoreService().initSemaphore(1);
  }

  void _waitSemaphore() async {
    print("Waiting for semaphore...");
    await SemaphoreService().waitSemaphore();
    print("Semaphore acquired!");
  }

  void _postSemaphore() async {
    print("Releasing semaphore...");
    await SemaphoreService().postSemaphore();
    print("Semaphore released!");
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Semaphore Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ElevatedButton(
                onPressed: _waitSemaphore,
                child: Text('Wait Semaphore'),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _postSemaphore,
                child: Text('Post Semaphore'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

这个示例展示了如何在Flutter应用中初始化、等待和释放信号量。请注意,原生代码部分需要根据实际需要进行调整,特别是信号量的存储和管理。

回到顶部