Flutter 插件数据回调

在编写Flutter插件时,涉及到结果回调、进度回调的时候。可以选择使用PlatformChannel、BlockCallback或FlutterEventChannel。下面简单说一下他们的使用场景。

1、PlatformChannel

PlatformChannel是Flutter与原生平台之间通信的桥梁。通过PlatformChannel,Flutter应用程序可以调用原生平台的API,同时原生平台也可以向Flutter应用程序发送消息。在数据回调场景中,可以使用PlatformChannelregisterMethodCallBack方法来注册一个回调函数,当在原生平台调用特定方法时,会触发这个回调函数。使用PlatformChannel需要手动处理原生平台和Flutter之间的数据转换。

优点:可以调用原生平台的任意方法,通信方式多样,包括异步和同步。

缺点:需要手动处理数据转换和回调,代码比较繁琐。

2、FlutterEventChannel

FlutterEventChannel是一种专门用于事件流处理的方式。它使用Flutter的Stream架构,可以通过Stream将数据从原生平台发送到Flutter应用程序。在Flutter插件中,可以使用FlutterEventChannel来定义事件流接口,原生平台通过这个接口向Flutter应用程序发送事件。

优点:支持异步事件流处理,不需要手动处理数据转换和回调,可以使用Dart的Stream处理库进行数据处理和转换。

缺点:需要熟悉Flutter的Stream架构和使用方式。

3、BlockCallback

BlockCallback是一种简单的回调方式,使用函数作为回调参数。在Flutter插件中,可以使用BlockCallback来定义原生平台需要调用的方法。这个方法的参数和返回值都是原生平台的类型,可以在Flutter应用程序中直接使用。

优点:使用简单,不需要手动处理数据转换和回调。

缺点:只能使用同步的方式进行通信,不适合处理大量数据或需要异步处理的情况。

4、总结

综上所述,PlatformChannel适用于需要调用原生平台任意方法的情况,可以使用异步或同步的方式进行通信;BlockCallback适用于简单的情况,使用同步方式进行通信;FlutterEventChannel适用于需要处理大量数据或需要异步处理的情况,使用异步事件流进行处理。根据具体需求选择合适的方式。

5、FlutterEventChannel的使用(Object_C版)

在插件的registerWithRegistrar方法中添加通道,如下:

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
    // 方法回调
    FlutterMethodChannel *channel = [FlutterMethodChannel
                                     methodChannelWithName:@"DemoPlugin"
                                     binaryMessenger:[registrar messenger]];
    // 通道1
    FlutterEventChannel *eventChannel1 = [FlutterEventChannel
                                                   eventChannelWithName:"eventChannel1"
                                                   binaryMessenger:[registrar messenger]];
    // 通道2
    FlutterEventChannel *eventChannel2 = [FlutterEventChannel
                                                  eventChannelWithName:"eventChannel2"
                                                  binaryMessenger:[registrar messenger]];
    // 通道3
    FlutterEventChannel *eventChannel3 = [FlutterEventChannel
                                                  eventChannelWithName:"eventChannel3"
                                                  binaryMessenger:[registrar messenger]];
    
    DemoPlugin *instance = [[DemoPlugin alloc] init];
    [registrar addMethodCallDelegate:instance channel:channel];
    [eventChannel1 setStreamHandler:instance];
    [eventChannel2 setStreamHandler:instance];
    [eventChannel3 setStreamHandler:instance];
}

Flutter端创建、销毁通道时,会自动进入iOS下面的代理:

// flutter创建通道/开启通道
- (FlutterError *)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)events {
    NSString *channelName = [NSString stringWithFormat:@"%@", arguments];
    if([channelName isEqualToString:@"eventChannel1"]){
        self.eventSink1 = events;
    }else if([channelName isEqualToString:2"eventChannel2"]){
        self.eventSink2 = events;
    }else if([channelName isEqualToString:@"eventChannel3"]){
        self.eventSink3 = events;
    }
    return nil;
}

// flutter关闭通道/销毁通道
- (FlutterError *)onCancelWithArguments:(id)arguments {
    NSString *channelName = [NSString stringWithFormat:@"%@", arguments];
    if([channelName isEqualToString:@"eventChannel1"]){
        self.eventSink1 = nil;
    }else if([channelName isEqualToString:2"eventChannel2"]){
        self.eventSink2 = nil;
    }else if([channelName isEqualToString:@"eventChannel3"]){
        self.eventSink3 = nil;
    }
    return nil;
}

回传演示:

if(self.eventSink1 != nil){
    self.eventSink1("demo1");
}

到此,iOS端所有的工作完成。

6、FlutterEventChannel的使用(flutter版)

6.1、创建通道
// 创建一个事件通道
EventChannel eventChannel1 = EventChannel('eventChannel1');
6.2、开启通道,即开始监听回传的信息

调用下面的方法,iOS端会自动触发onListenWithArguments的代理,完成通道开启。这里需要给receiveBroadcastStream()加一个参数,用于区分当前通道是哪一个。

// 监听来自原生端的事件流
late StreamSubscription streamSubscription1 =  = eventChannel1.receiveBroadcastStream("eventChannel1").listen((event) {
      
});;

这里需要说明下,为什么创建通道使用了'eventChannel1',监听事件流又使用到了'eventChannel1'

  • 1、6.1中的是'eventChannel1'完成了通道的创建,需要和插件中的通道名一致。

  • 2、6.2中的是'eventChannel1'是事件流的监听,因为存在多个通道,iOS端在接收到onListenWithArguments回调时,无法知道创建的是哪一个通道,所以需要在receiveBroadcastStream("eventChannel1")这里再重新写一遍'eventChannel1',这样iOS就能判断出当前是哪一个通道在工作/关闭。

当然事件流这里的参数也可以换一个名称,和通道名区分开,看自己喜好。

6.3关闭通道

调用下面的方法,iOS端会自动触发onCancelWithArguments的代理,完成通道的销毁。

streamSubscription1.cancel();
Flutter中实现本地数据持久化有多种方式,比如使用shared_preferences、sqflite、path_provider等插件。下面以shared_preferences为例,介绍如何实现输入数据的本地存储和读取。 首先,在`pubspec.yaml`文件中添加依赖: ```yaml dependencies: shared_preferences: ^2.0.6 ``` 然后,在需要存储数据的页面,我们可以使用如下代码将输入的数据存储到本地: ```dart import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; class InputPage extends StatefulWidget { @override _InputPageState createState() => _InputPageState(); } class _InputPageState extends State<InputPage> { TextEditingController _textEditingController = TextEditingController(); String _inputData = ''; @override void initState() { super.initState(); _loadData(); } @override void dispose() { _textEditingController.dispose(); super.dispose(); } Future<void> _loadData() async { SharedPreferences prefs = await SharedPreferences.getInstance(); setState(() { _inputData = prefs.getString('input_data') ?? ''; _textEditingController.text = _inputData; }); } Future<void> _saveData(String data) async { SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('input_data', data); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('输入页面'), ), body: Padding( padding: EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '请输入数据:', style: TextStyle( fontSize: 16.0, ), ), SizedBox(height: 10.0), TextField( controller: _textEditingController, onChanged: (value) { _saveData(value); }, decoration: InputDecoration( hintText: '请输入', ), ), SizedBox(height: 20.0), Text( '输入的数据是:$_inputData', style: TextStyle( fontSize: 16.0, ), ), ], ), ), ); } } ``` 在上面的代码中,我们首先在`initState`方法中调用了`_loadData`方法,从本地存储中加载数据并将其设置到文本输入框中。`_loadData`方法中,我们使用`SharedPreferences`插件获取实例,并调用`getString`方法获取之前存储的数据,如果之前没有存储数据则返回默认值''。然后,我们在`TextField`的`onChanged`回调中调用`_saveData`方法,将输入的数据保存到本地。`_saveData`方法中,我们同样使用`SharedPreferences`插件获取实例,并调用`setString`方法将数据存储到本地。 这样,输入的数据就可以实现本地持久化了。每次打开应用时,都会从本地存储中加载之前输入的数据,并将其设置到文本输入框中。如果用户修改了输入的数据,就会自动保存到本地。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值