【Flutter】三个Channel(Android-java / Ios-swift)

Channel

实现与原生通信

【1】MethodChannel

flutter MethodChannel官方文档
通过MethodChannel来传递数据,调用方法

案例

分别调用Android和Ios原生的获取电量的方法

Flutter端

实例一个MethodChannel, 唯一标识name,定义方法名称getBatteryLevel
在这里插入图片描述
methodchannel.invokeMethod(name)来调用方法

  static const platform = MethodChannel('sample.flutter.dev/battery');
  static const method = 'getBatteryLevel';
  String _batteryLevel = 'Unknown battery level';

  Future<void> _getBatteryLevel() async {
    String batteryLevel;
    try {
      final result = await platform.invokeMethod<int>(method);
      batteryLevel = 'Battery level at $result';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}";
    }
    setState(() {
      _batteryLevel = batteryLevel;
    });
  }

界面操作

  
  Widget build(BuildContext context) {
    return Material(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          ElevatedButton(
            onPressed: _getBatteryLevel,
            child: const Text('Get Battery Level'),
          ),
          Text(_batteryLevel),
        ],
      ),
    );
  }
Android端

在这里插入图片描述

    private static final String CHANNEL = "sample.flutter.dev/battery";
    private MethodChannel methodChannel;

    private static final String METHOD = "getBatteryLevel";

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        BinaryMessenger binaryMessenger = flutterEngine.getDartExecutor().getBinaryMessenger();
        methodChannel = new MethodChannel(binaryMessenger, CHANNEL);
        methodChannel.setMethodCallHandler((call, result) -> {
            
        });
    }

在这里插入图片描述

if (call.method.equals(METHOD)) {
                int batteryLevel = getBatteryLevel();
                if (batteryLevel != -1) {
                    result.success(batteryLevel);
                } else {
                    result.error("UNAVAILABLE", "Battery level not avaiable", null);
                }
            } else {
                result.notImplemented();
            }
private int getBatteryLevel() {
        int batteryLevel = -1;
        if (VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE);
            batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        } else {
            IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
            Intent intent = new ContextWrapper(getApplicationContext()).registerReceiver(null, intentFilter);
            batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) /
                    intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
        }
        return batteryLevel;
    }
Ios端

实例FlutterMethodChannel
在这里插入图片描述

override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
      let method : String = "getBatteryLevel"
      let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
      let batteryChannel = FlutterMethodChannel(name: "sample.flutter.dev/battery", binaryMessenger: controller.binaryMessenger)
      batteryChannel.setMethodCallHandler({
          (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
          guard call.method == method else {
              result(FlutterMethodNotImplemented)
              return
          }
          self.receiveBatteryLevel(result: result)
      })
      GeneratedPluginRegistrant.register(with: self)
      return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

定义获取电量的方法

func receiveBatteryLevel(result: FlutterResult) -> Void {
        let device = UIDevice.current
        device.isBatteryMonitoringEnabled = true
        if device.batteryState == UIDevice.BatteryState.unknown {
            result(FlutterError(code: "UNAVAILABLE", message: "Battery level not available.", details: nil))
        } else {
            result(Int(device.batteryLevel * 100))
        }
    }
运行测试

在这里插入图片描述

【2】EventChannel

墙外的参考文章
区别MethodChannel,它是continuously
采用event streams

案例

在原生端(Android&Ios)会有个计时器,不停的传时间给Flutter端,Flutter端显示出来

Flutter端

实例一个EventChannel,唯一标识name
在这里插入图片描述

  late EventChannel eventChannel;

  
  void initState() {
    eventChannel = const EventChannel('timeHandlerEvent');
    super.initState();
  }

在Flutter注册监听
在这里插入图片描述

Stream<String> get streamTimeFromNative =>
      eventChannel.receiveBroadcastStream().map((event) => event.toString());

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: StreamBuilder<String>(
          stream: streamTimeFromNative,
          builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
            if (snapshot.hasData) {
              return Text(
                '${snapshot.data}',
                style: Theme.of(context).textTheme.headlineMedium,
              );
            } else {
              return const CircularProgressIndicator();
            }
          },
        ),
      ),
    );
  }
Ios端

实例一个FlutterEventChannel,加上唯一标识timeHandlerEvent
在这里插入图片描述

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
      let eventChannel = FlutterEventChannel(name: "timeHandlerEvent", binaryMessenger: controller.binaryMessenger)

定义FlutterStreamHandler

class TimeHandler: NSObject, FlutterStreamHandler {
        func onCancel(withArguments arguments: Any?) -> FlutterError? {
            return nil
        }
        
        func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {
            return nil
        }
    }

每间隔1秒发送一次当前时间

    class TimeHandler: NSObject, FlutterStreamHandler {
        var timer = Timer()
        private var eventSink: FlutterEventSink?
        
        func onCancel(withArguments arguments: Any?) -> FlutterError? {
            eventSink = nil
            return nil
        }
        
        func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {
            self.eventSink = eventSink
            self.timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: {_ in 
                let dateFormat = DateFormatter()
                dateFormat.dateFormat = "HH:mm:ss"
                let time = dateFormat.string(from: Date())
                eventSink(time)
            })
            return nil
        }
    }

注册监听

eventChannel.setStreamHandler(TimeHandler())

在这里插入图片描述

Android端

new 一个EventChannel对象
在这里插入图片描述
在channel注册一个stream Handler
在这里插入图片描述
在这里插入图片描述

        EventChannel.StreamHandler streamHandler = new EventChannel.StreamHandler() {
            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
            }

            @Override
            public void onCancel(Object arguments) {
            }
        };
        eventChannel.setStreamHandler(streamHandler);

不断将当前时间返回
在这里插入图片描述

EventChannel.StreamHandler streamHandler = new EventChannel.StreamHandler() {
            private final Handler handler = new Handler(Looper.getMainLooper());

            private EventChannel.EventSink eventSink = null;

            @Override
            public void onListen(Object arguments, EventChannel.EventSink events) {
                eventSink = events;
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        Locale locale = new Locale("zh", "CN");
                        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss", locale);
                        String time = dateFormat.format(new Date());
                        events.success(time);
                        handler.postDelayed(this, 1000);
                    }
                };
                handler.postDelayed(runnable, 1000);
            }

            @Override
            public void onCancel(Object arguments) {
                eventSink = null;
            }
        };
        eventChannel.setStreamHandler(streamHandler);
运行测试

在建立好EventChannel之后,运行项目。
在这里插入图片描述
获取到当前的时间,并且不停的

【3】BasicMessageChannel

参考文章
约定一种数据格式,来互相传递数据

案例

传递Map数据到Android/Ios端,再解析并返回数据到Flutter端

Flutter端

构建BasicMessageChannel, 唯一标识name,约定数据格式StandardMessageCodec

static const messageChannel =
      BasicMessageChannel('basic_message_channel', StandardMessageCodec());

发送数据

Map<String, dynamic> message = {
                  "name": "apple",
                  "time": "2024-04-09 12:30:00"
                };
messageChannel.send(arguments)

接收数据

Map reply = await messageChannel.send(arguments) as Map;

在这里插入图片描述

Android 端

接收数据

messageChannel.setMessageHandler((message, reply) -> {});

发送数据

reply.reply(resultMap);

在这里插入图片描述

package com.example.basic_message_channel_example;

import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.StandardMessageCodec;

public class MainActivity extends FlutterActivity {

    @Override
    public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
        super.configureFlutterEngine(flutterEngine);
        BinaryMessenger binaryMessenger = Objects.requireNonNull(getFlutterEngine()).getDartExecutor().getBinaryMessenger();
        BasicMessageChannel<Object> messageChannel = new BasicMessageChannel<Object>(binaryMessenger, "basic_message_channel", StandardMessageCodec.INSTANCE);
        messageChannel.setMessageHandler((message, reply) -> {
            Map<Object, Object> arguments = (Map<Object, Object>) message;
            assert message != null;
            String name = (String) arguments.get("name");
            assert name != null;
            if (name.equals("apple")) {
                Map<String, Object> resultMap = new HashMap<>();
                String timeStr = (String) arguments.get("time");
                Timestamp timestamp = Timestamp.valueOf(timeStr);
                resultMap.put("message", "i eat the " + name + " at " + timestamp.toString());
                resultMap.put("code", 200);
                reply.reply(resultMap);
            } else {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("message", "i dislike " + name);
                resultMap.put("code", 500);
                reply.reply(resultMap);
            }
        });
    }
}

Ios 端

构建通道

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let basicMessageChannel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: controller.binaryMessenger)

接收数据

      basicMessageChannel.setMessageHandler { message, reply in
          
      }

返回数据

reply(result)

在这里插入图片描述

import UIKit
import Flutter

@available(iOS 15.0, *)
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
      let channelName : String = "basic_message_channel"
      let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
      let basicMessageChannel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: controller.binaryMessenger)
      basicMessageChannel.setMessageHandler { message, reply in
          if let data = message as? Dictionary<String, Any> {
              let name: String = data["name"] as? String ?? ""
              if name == "apple" {
                  let timeStr: String = data["time"] as? String ?? ""
                  var message: String = "I eat the "
                  message.append(name)
                  message.append(" at ")
                  message.append(timeStr)
                  let result = ["code": 200, "message": message]
                  reply(result)
              } else {
                  var message = "I dislike "
                  message.append(name)
                  let result = ["code": 500, "message": message]
                  reply(result)
              }
          }
      }
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}
运行测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结

MethodChannel 定义方法名调用
EventChannel 持续监听数据传递
BasicMessageChannel 约定一种数据格式,传递数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/530372.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux大文件IO

在Linux中处理大文件&#xff08;通常指大小超过2GB的文件&#xff09;时&#xff0c;需要使用特定的系统调用和标志&#xff0c;以确保程序能够正确地处理大文件的读写。这主要是因为在32位系统上&#xff0c;传统的文件偏移量和文件大小使用off_t类型表示&#xff0c;它通常是…

RabbitMQ的自动应答和手动应答,解决重试死循环

RabbitMQ的自动应答和手动应答&#xff0c;解决重试死循环 1.应答模式 RabbitMQ 中的消息应答模式主要包括两种&#xff1a;自动应答&#xff08;Automatic Acknowledgement&#xff09;和手动应答&#xff08;Manual Acknowledgement&#xff09;。 1、自动应答&#xff1a;…

ctfshow web入门 文件上传web162--web167

web162 session文件包含条件竞争 直接包含不传马了 我们上传的文件如果不符合要求&#xff0c;就会被删除&#xff0c;导致成功上传无法访问&#xff0c;没有用。但是如果我们上传的速度比服务器删的速度快&#xff0c;就可以了。 上传.user.ini GIF89a auto_append_file/tmp/…

医院预约系统微信小程序APP前后端

医院预约系统具体功能介绍&#xff1a;展示信息、可以注册和登录&#xff0c; 预约&#xff08;包含各个科室的预约&#xff0c;可以预约每个各个医生&#xff09;&#xff0c;就诊引导包含预约的具体信息&#xff0c;包含就诊时间、就诊科室、就诊医生以及就诊人信息、和支付状…

Unity之Unity面试题(三)

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之Unity面试题&#xff08;三&#xff09; TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取…

2025考研数学汤家凤基础班百度网盘视频+强化班PDF讲义持续更新

如果25考研想全程跟张宇老师&#xff0c;可以参考下面这个表格来使用资料&#xff1a; 2025考研数学全程课&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1e6wA4OiH_EJpZPXPxoHYwg 提取码&#xff1a;om45 考研数学 考研数学无非就是汤家凤老师&#xff0c;张宇老师…

政安晨:【深度学习神经网络基础】(五)—— 霍普菲尔德神经网络和玻尔兹曼机

目录 简述 霍普菲尔德神经网络 训练霍普菲尔德神经网络 Hopfield-Tank神经网络 玻尔兹曼机 总之 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&am…

Linux安装Oracle11g(无图形界面下的静默安装)

Oracle11g安装文档-Linux静默安装 环境准备安装数据库配置监听器创建数据库测试打开防火墙 环境准备 创建组和用户 [rootlocalhost ~]# groupadd oinstall #创建oinstall组 [rootlocalhost ~]# groupadd dba  #创建dba组 [rootlocalhost ~]# useradd -g oinstall -G dba -m…

【快捷部署】016_Ollama(CPU only版)

&#x1f4e3;【快捷部署系列】016期信息 编号选型版本操作系统部署形式部署模式复检时间016Ollama&#xff08;CPU only&#xff09;latestCentOS 7.XDocker单机2024-04-10 注意事项&#xff1a; 1、目前镜像及大模型下载速度尚可&#xff0c;但由于容量较大&#xff0c;所以…

K8S:常用资源对象操作

文章目录 一、使用Replication Controller(RC)、Replica Set(RS) 管理Pod1 Replication Controller&#xff08;RC&#xff09;2 Replication Set&#xff08;RS&#xff09; 二、Deployment的使用1 创建2 滚动升级3 回滚Deployment三、 Pod 自动扩缩容HPA1 使用kubectl autosc…

thinkphp5关联预载入with指定字段属性查询

一、thinkphp5.0 如果要指定属性查询&#xff0c;可以使用&#xff1a; $list User::field(id,name)->with([profile>function($query){$query->field(email,phone);}])->select([1,2,3]); foreach($list as $user){// 获取用户关联的profile模型数据dump($user…

典型新能源汽车热管理系统方案分析

目前行业具有代表性的热管理系统有PTC电加热方案、热泵方案&#xff08;特斯拉八通阀热泵、吉利直接式热泵&#xff09;、威马的柴油加热方案以及以理想为代表的插电式混动车方案。 小鹏P7整车热管理方案分析&#xff08;PTC电加热方案&#xff09; 小鹏P7作为小鹏汽车的第2款…

NzN的数据结构--插入排序

排序排序我要Disney&#xff0c;今天我们先来看看经典排序算法里的插入排序&#xff0c;先三连后看才是好习惯&#xff01;&#xff01;&#xff01; 目录 一、排序的概念及应用 1. 排序的概念 2. 排序的应用 3. 常见的排序算法 二、插入排序 1. 基本思想 2. 直接插入排…

pyside6的QSpinBox自定义特性初步研究(二)

当前的需求是&#xff0c;蓝色背景的画面&#xff0c;需要一个相对应色系的QSpinBox部件。已有的部件风格是这样的&#xff0c;需要新的部件与之般配。 首先新建一个QDoubleSpinBox&#xff0c;并定义其背景色和边框&#xff1a; QDoubleSpinBox { color: white; border:1px…

Vue3---基础1(认识,创建)

变化 相对于Vue2&#xff0c;Vue3的变化&#xff1a; 性能的提升 打包大小减少 41% 初次渲染快 55%&#xff0c;更新渲染快133% 内存减少54% 源码的升级 使用 proxy 代替 defineProperty 实现响应式 重写虚拟 DOM 的实现和 Tree-shaking TypeScript Vue3就可以更好的支持TypeSc…

Python:如何对FY3D TSHS的数据集进行重投影并输出为TIFF文件以及批量镶嵌插值?

完整代码见 Github&#xff1a;https://github.com/ChaoQiezi/read_fy3d_tshs&#xff0c;由于代码中注释较为详细&#xff0c;因此博客中部分操作一笔带过。 01 FY3D的HDF转TIFF 1.1 数据集说明 FY3D TSHS数据集是二级产品(TSHS即MWTS/MWHS 融合大气温湿度廓线/稳定度指数/…

ssm“最多跑一次”微信小程序

采用技术 ssm“最多跑一次”微信小程序的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringMVCMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统实现的功能 本次设计任务是要设计一个“最多跑一次”微信小程序&#xff0c;…

【攻防世界】php_rce (ThinkPHP5)

进入题目环境&#xff0c;查看页面信息&#xff1a; 页面提示 ThinkPHP V5&#xff0c;猜测存在ThinkPHP5 版本框架的漏洞&#xff0c;于是查找 ThinkPHP5 的攻击POC。 构造 payload: http://61.147.171.105:50126/?sindex/think\app/invokefunction&functioncall_user_f…

JVM-结合MAT工具分析OOM问题

JVM-结合MAT工具分析OOM问题 启动项目前配置VM参数 -XX:UseParNewGC -XX:UseConcMarkSweepGC -Xms1m #初始化大小 -Xmx1m #最大值 -XX:PrintGCDetails -Xloggc:gc_dandan.log -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath./运行结果截图 使用MAT打开java_pid12164.hprof…

开源铱塔切换MySQL数据库启动报异常

1.错误日志&#xff1a; 铱塔切换数据库配置为MySQL之后&#xff0c;启动后报错如下&#xff1a; SqlExceptionHelper - Table iotkit.task_info doesnt exist SqlExceptionHelper - Table iotkit.rule_info doesnt exist SqlExceptionHelper - Table iotkit.device_info does…