【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";@Overridepublic 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! FlutterViewControllerlet batteryChannel = FlutterMethodChannel(name: "sample.flutter.dev/battery", binaryMessenger: controller.binaryMessenger)batteryChannel.setMethodCallHandler({(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void inguard 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.currentdevice.isBatteryMonitoringEnabled = trueif 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! FlutterViewControllerlet 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 = nilreturn nil}func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? {self.eventSink = eventSinkself.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() {@Overridepublic void onListen(Object arguments, EventChannel.EventSink events) {}@Overridepublic 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;@Overridepublic void onListen(Object arguments, EventChannel.EventSink events) {eventSink = events;Runnable runnable = new Runnable() {@Overridepublic 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);}@Overridepublic 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 {@Overridepublic 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! FlutterViewControllerlet basicMessageChannel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: controller.binaryMessenger)basicMessageChannel.setMessageHandler { message, reply inif 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 约定一种数据格式,传递数据

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信小程序Skyline模式下瀑布长列表优化成虚拟列表,解决内存问题

微信小程序长列表&#xff0c;渲染的越多就会导致内存吃的越多。特别是长列表的图片组件和广告组件。 为了解决内存问题&#xff0c;所以看了很多人的资料&#xff0c;都不太符合通用的解决方式&#xff0c;很多需要固定子组件高度&#xff0c;但是瀑布流是无法固定的&#xf…

MYSQL 8.0版本修改用户密码(知道登录密码)和Sqlyog错误码2058一案

今天准备使用sqlyog连接一下我Linux上面的mysql数据库&#xff0c;然后就报如下错误 有一个简单的办法就是修改密码为password就完事!然后我就开始查找如何修改密码! 如果是需要解决Sqlyog错误码2058的话&#xff0c;执行以下命令&#xff0c;但是注意root对应host是不是loca…

开源铱塔切换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…

Word 画三线表模板---一键套用

1、制作三线表 1&#xff09;设置为无边框 选中表格&#xff0c;点击「右键」——「边框」——「无框线」。 2&#xff09;添加上下边框线 选中表格后&#xff0c;点击【右键】——【表格属性】——【边框和底纹】&#xff0c;边框线选择【1.5磅】&#xff0c;然后点击【上框…

JavaScript - 请你为数组自定义一个方法myFind,使其实现find方法的功能

难度级别:中级及以上 提问概率:50% 我们知道数组的find方法是ES6之后出现的,它强调找到第一个符合条件的元素后即跳出循环,不再继续执行,那么如果不用ES6的知识,为数组添加一个自定义方法实现find方法的功能,首先要想到在数组的原型pro…

解决MySQL服务无法启动问题

本地计算机上的 mysq 服务启动后停止。某些服务在未由其他服务或程序使用时将自动停止。 笔记本电脑上的MySQL也是经常在使用的&#xff0c;有一天使用dbeaver连接时突然就连接不上了&#xff01;&#xff01;&#xff01;分析报错信息&#xff0c;也不是口令问题&#xff01;于…

抓住风口,快速上手RAG应用开发!

免责声明~ 任何文章不要过度深思&#xff01; 万事万物都经不起审视&#xff0c;因为世上没有同样的成长环境&#xff0c;也没有同样的认知水平&#xff0c;更「没有适用于所有人的解决方案」&#xff1b; 不要急着评判文章列出的观点&#xff0c;只需代入其中&#xff0c;适度…

c++的学习之路:20、继承(1)

摘要 本章主要是讲以一下继承的一些概念以及使用方法等等。 目录 摘要 一、继承的概念及定义 1、继承的概念 2、继承定义 1.2.1、定义格式 1.2.2、继承关系和访问限定符 1.2.3、继承基类成员访问方式的变化 3、总结 二、基类和派生类对象赋值转换 三、继承中的作用…

【Qt 学习笔记】Qt信号和槽的其他说明及Lambda表达式

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt信号和槽的其他说明及Lambda表达式 文章编号&#xff1a;Qt 学习笔记…

JVS-智能BI数据分析:数仓+流程化加工的独特优势

在JVS-BI中采用了数仓流程化加工的方式进行数据分析&#xff0c;主要涉及到数据的离线抽取&#xff0c;流程化加工&#xff0c;生成标准的数据分析结果。 下面我们先看下什么是数仓&#xff1a; 数仓&#xff08;Data Warehouse&#xff09;是一个用于集中存储和管理企业中各种…

iOS 开发中上传 IPA 文件的方法(无需 Mac 电脑)

引言 在 iOS 开发中&#xff0c;将 IPA 文件上传到苹果开发者中心是一个重要的步骤。通常情况下&#xff0c;我们需要使用 Mac 电脑上的 Xcode 或 Application Loader 工具来完成这个任务。然而&#xff0c;如果你没有 Mac 电脑&#xff0c;也没有关系&#xff0c;本文将介绍一…

2024 抖音欢笑中国年(三):编辑器技巧与实践

前言 本次春节活动中&#xff0c;我们大部分场景使用内部的 SAR Creator互动方案来实现。 SAR Creator 是一款基于 TypeScript 的高性能、轻量化的互动解决方案&#xff0c;目前支持了Web和字节内部跨端框架平台&#xff0c;服务于字节内部的各种互动业务&#xff0c;包括但不限…

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

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

保研线性代数复习4

一.范数&#xff08;Norms&#xff09; 1.什么是范数&#xff1f; 范数是一个向量空间V的函数&#xff0c;每一个属于向量空间V的向量x都匹配了一个实数&#xff08;它的长度&#xff09;&#xff1a; 2.范数的性质&#xff1f; 齐次性&#xff1a; 正定性&#xff1a; 三…

网络安全之权限维持那点事

权限维持 一旦黑客成功地入侵了目标系统&#xff0c;他们通常会尝试保持对系统的持久访问权&#xff0c;以便继续执行恶意活动&#xff0c;如窃取敏感数据、植入恶意软件、破坏系统功能等。 权限维持的过程可能包括以下几个方面&#xff1a; 后门植入&#xff1a;黑客可能会在…

easyExcel - 动态复杂表头的编写

目录 前言一、情景介绍二、问题分析三、代码实现方式一&#xff1a;head 设置方式二&#xff1a;模板导出方式三&#xff1a;自定义工具类 前言 Java-easyExcel入门教程&#xff1a;https://blog.csdn.net/xhmico/article/details/134714025 之前有介绍过如何使用 easyExcel&…

CSS-浮动文字环绕布局、隐藏属性display、overflow、三角形制作、鼠标样式

文字环绕布局 CSS文字环绕布局是指在网页中让文字环绕在图片或其他元素周围的布局方式。这通常通过CSS中的float属性来实现。你可以将图片设置为float: left;或float: right;&#xff0c;然后在文本元素中使用clear属性来清除浮动&#xff0c;以确保文字不会覆盖图片。另外&am…

Jmeter02-2:参数化组件其他方式

0、Jmeter组件&#xff1a;参数化概述 0.1 是什么&#xff1f; 参数化是动态的获取并设置数据 0.2 为什么&#xff1f; 比如执行批量操作时&#xff0c;批量插入或批量删除&#xff0c;之前数据都是手写的&#xff0c;每执行完都要修改一次&#xff0c;效率太低 而参数化就是…

基于javassmJSP的教学质量评价系统

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

maxpool long数据类型报错

报错&#xff1a; RuntimeError: “max_pool2d” not implemented for ‘Long’ 源码&#xff1a; import torch from torch import nn from torch.nn import MaxPool2dinput torch.tensor([[1, 2, 0, 3, 1],[0, 1, 2, 3, 1],[1, 2, 1, 0, 0],[5, 2, 3, 1, 1],[2, 1, 0, 1, 1…