Flutter数据流通信插件streams_channel3的使用

Flutter数据流通信插件streams_channel3的使用

StreamsChannel for Flutter插件开发

pub package

StreamsChannel是受EventChannel启发而创建的。它允许在Flutter和平台端之间创建事件流。

理由

EventChannel仅允许每个通道创建一个开放的流。第一次订阅时,该流将被打开,并且可以从Flutter向平台端传递参数。后续订阅将重用先前打开的流或使用新的参数覆盖它。

为了在同一时间支持多个开放的流,且这些流具有不同的初始化参数,必须为每个流创建多个EventChannel。如果流的数量是动态的,这会变得复杂。

安装

请参考以下说明进行安装:

https://pub.dev/packages/streams_channel#-installing-tab-

如何工作

StreamsChannel的工作方式与EventChannel类似,区别在于它支持在同一时间打开多个流。

在平台端,通道接收一个流处理器工厂:

let channel = FlutterStreamsChannel(name: "my_channel", binaryMessenger: plugin.registrar.messenger())
channel.setStreamHandlerFactory { arguments in
  return MyHandler(arguments) // MyHandler是一个FlutterStreamHandler实例
}

在Flutter端,每次调用receiveBroadcastStream(args)都会创建一个新的流,不会替换任何仍在运行的先前流。

  1. 第一次订阅流时,将使用平台端的工厂创建一个新的流处理器,然后触发处理器上的onListen
  2. 最后一次订阅流时,将触发处理器上的onCancel,然后销毁处理器实例;
  3. 如果之后再次发生第一次订阅,则重复步骤1。

底层实现中,StreamsChannel使用简单的自增唯一ID来跟踪每个流。

示例

Flutter端
final StreamsChannel channel = new StreamsChannel('some_channel');

// 持续从平台端接收事件,匹配某些参数
channel.receiveBroadcastStream('some args')
  .listen((data) {
    // 处理数据
  });

// 另一个持续从平台端接收事件,匹配其他参数
channel.receiveBroadcastStream('some other args')
  .listen((data) {
    // 处理数据
  });
平台端
Android
public class DemoPlugin {
  public static void registerWith(PluginRegistry.Registrar registrar) {
    final StreamsChannel channel = new StreamsChannel(registrar.messenger(), "streams_channel_test");
    channel.setStreamHandlerFactory(new StreamsChannel.StreamHandlerFactory() {
      @Override
      public EventChannel.StreamHandler create(Object arguments) {
        return new StreamHandler();
      }
    });
  }

  // 发送"Hello" 10次,每秒发送一次,然后结束流
  public static class StreamHandler implements EventChannel.StreamHandler {

    private final Handler handler = new Handler();
    private final Runnable runnable = new Runnable() {
      @Override
      public void run() {
        if (count > 10) {
            eventSink.endOfStream();
        } else {
            eventSink.success("Hello " + count + "/10");
        }
        count++;
        handler.postDelayed(this, 1000);
      }
    };

    private EventChannel.EventSink eventSink;
    private int count = 1;

    @Override
    public void onListen(Object o, final EventChannel.EventSink eventSink) {
      this.eventSink = eventSink;
      runnable.run();
    }

    @Override
    public void onCancel(Object o) {
      handler.removeCallbacks(runnable);
    }
  }
}
iOS
@interface StreamHandler : NSObject<FlutterStreamHandler>
  @property(strong, nonatomic) NSTimer *timer;
  @property(assign, nonatomic) NSInteger count;
@end

@implementation DemoPlugin

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {

  FlutterStreamsChannel *channel = [FlutterStreamsChannel streamsChannelWithName:@"streams_channel_test" binaryMessenger:registrar.messenger];
  [channel setStreamHandlerFactory:^NSObject<FlutterStreamHandler> *(id arguments) {
    return [StreamHandler new];
  }];
}

@end

// 发送"Hello" 10次,每秒发送一次,然后结束流
@implementation StreamHandler

- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events {
  self.count = 1;
  self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
    if(self.count > 10) {
      events(FlutterEndOfEventStream);
    } else {
      events([NSString stringWithFormat:@"Hello %ld/10", (long)self.count]);
      self.count++;
    }
  }];

  return nil;
}

- (FlutterError *)onCancelWithArguments:(id)arguments {
  [self.timer invalidate];
  self.timer = nil;
  return nil;
}
@end

示例代码

// Copyright (c) 2021 Kfir Matityahu
// Licensed under Apache License v2.0

import 'dart:async';

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

void main() => runApp(MyApp());

final StreamsChannel streamsChannel = StreamsChannel('streams_channel_example');

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

class _MyAppState extends State<MyApp> {
  StreamSubscription<dynamic>? _subscriptionA;
  StreamSubscription<dynamic>? _subscriptionB;

  void _start(bool a) {
    // 忽略取消订阅
    StreamSubscription<dynamic>? subscription = a ? _subscriptionA : _subscriptionB;

    if (subscription != null) {
      subscription.cancel();
      subscription = null;
    } else {
      final streamId = 'Stream ${a ? 'A' : 'B'}';
      subscription = streamsChannel
          .receiveBroadcastStream(streamId)
          .listen((data) => debugPrint('Received from $streamId: $data'));

      subscription.onDone(() {
        setState(() {
          if (a) {
            _subscriptionA = null;
          } else {
            _subscriptionB = null;
          }
        });
      });
    }

    setState(() {
      if (a) {
        _subscriptionA = subscription;
      } else {
        _subscriptionB = subscription;
      }
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Demo'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              FlatButton(
                onPressed: () => _start(true),
                child: Text(_subscriptionA != null ? '停止 A' : '开始 A'),
              ),
              FlatButton(
                onPressed: () => _start(false),
                child: Text(_subscriptionB != null ? '停止 B' : '开始 B'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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

1 回复

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


streams_channel 是一个用于在 Flutter 和原生平台(Android 和 iOS)之间进行双向数据流通信的插件。它允许你在 Flutter 和原生代码之间发送和接收数据流。streams_channel3streams_channel 的一个版本,适用于 Flutter 3.x 及以上版本。

安装

首先,在你的 pubspec.yaml 文件中添加 streams_channel 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  streams_channel: ^3.0.0

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

使用示例

1. 在 Flutter 中创建 StreamsChannel

首先,在 Flutter 中创建一个 StreamsChannel 实例。这个通道将用于与原生平台进行通信。

import 'package:streams_channel/streams_channel.dart';

final streamsChannel = StreamsChannel('com.example.my_channel');

2. 在 Flutter 中发送数据到原生平台

你可以使用 send 方法向原生平台发送数据:

streamsChannel.send('Hello from Flutter');

3. 在 Flutter 中接收来自原生平台的数据

你可以通过监听 stream 来接收来自原生平台的数据:

streamsChannel.stream.listen((data) {
  print('Received data from native: $data');
});

4. 在原生平台中处理数据

在原生平台(Android 或 iOS)中,你需要设置一个对应的通道来接收和处理来自 Flutter 的数据,并向 Flutter 发送数据。

Android (Kotlin)

在 Android 中,你可以使用 EventChannel 来处理数据流通信。

import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.EventChannel.EventSink
import io.flutter.plugin.common.EventChannel.StreamHandler
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import io.flutter.plugin.common.PluginRegistry.Registrar

class MyPlugin(private val registrar: Registrar) : StreamHandler {

    companion object {
        fun registerWith(registrar: Registrar) {
            val channel = EventChannel(registrar.messenger(), "com.example.my_channel")
            channel.setStreamHandler(MyPlugin(registrar))
        }
    }

    override fun onListen(arguments: Any?, events: EventSink?) {
        // 处理来自 Flutter 的监听请求
        events?.success("Hello from Android")
    }

    override fun onCancel(arguments: Any?) {
        // 处理 Flutter 取消监听的请求
    }
}

MainActivity 中注册插件:

import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MyPlugin.registerWith(flutterEngine.dartExecutor.binaryMessenger)
    }
}
iOS (Swift)

在 iOS 中,你可以使用 FlutterEventChannel 来处理数据流通信。

import Flutter
import UIKit

public class SwiftMyPlugin: NSObject, FlutterPlugin, FlutterStreamHandler {
    private var eventSink: FlutterEventSink?

    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterEventChannel(name: "com.example.my_channel", binaryMessenger: registrar.messenger())
        let instance = SwiftMyPlugin()
        channel.setStreamHandler(instance)
    }

    public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        self.eventSink = events
        events("Hello from iOS")
        return nil
    }

    public func onCancel(withArguments arguments: Any?) -> FlutterError? {
        eventSink = nil
        return nil
    }
}

AppDelegate 中注册插件:

import UIKit
import Flutter

[@UIApplicationMain](/user/UIApplicationMain)
[@objc](/user/objc) class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        SwiftMyPlugin.register(with: registrar(forPlugin: "MyPlugin")!)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}
回到顶部