当前位置:网站首页>Flutter实战-自定义键盘(三)
Flutter实战-自定义键盘(三)
2022-07-21 21:14:00 【蓝面书生】
用了两年的flutter,有了一些心得,从今天开始陆续更新一些案例,不虚头巴脑,只求实战有用,以供学习或使用flutter的小伙伴参考,学习尚浅,如有不正确的地方还望各路大神指正,以免误人子弟,在此拜谢~(原创不易,转发请标注来源和作者)
注意:无特殊说明,flutter版本为3.0+
当初写该组件的时候flutter的版本是2.1,直到有一天flutter 升级到2.5版本后,发现键盘突然不能用了,发现是官方废弃了TestDefaultBinaryMessenger,
/// [WidgetTester], [TestWidgetsFlutterBinding], [TestDefaultBinaryMessenger],
/// and [TestDefaultBinaryMessenger.handlePlatformMessage] respectively).
///
/// To register a handler for a given message channel, see [setMessageHandler].
///
/// To send a message _to_ a plugin on the platform thread, see [send].
// TODO(ianh): deprecate this method once cocoon and other customer_tests are migrated:
// @NotYetDeprecated(
// 'Instead of calling this method, use ServicesBinding.instance.channelBuffers.push. '
// 'In tests, consider using tester.binding.defaultBinaryMessenger.handlePlatformMessage '
// 'or TestDefaultBinaryMessenger.instance.defaultBinaryMessenger.handlePlatformMessage. '
// 'This feature was deprecated after v2.1.0-10.0.pre.'
// )
Future<void> handlePlatformMessage(String channel, ByteData? data, ui.PlatformMessageResponseCallback? callback);
当时cool_ui的作者也没有发布新版本,那么如何解决这个问题呢,那就是重新写一个自己的BinaryMessenger。
一.定义自己的WidgetsFlutterBinding
不了解WidgetsFlutterBinding 的读者可以看我之前的文章,那首先我们要复写ServicesBingding,这个bingding是 用来处理flutter和原生交互用的
class MyWidgetsFlutterBinding extends WidgetsFlutterBinding with MyServicesBinding {
static WidgetsBinding? ensureInitialized() {
MyWidgetsFlutterBinding();
return WidgetsBinding.instance;
}
}
mixin MyServicesBinding on BindingBase, ServicesBinding {
@override
BinaryMessenger createBinaryMessenger() {
return TestDefaultBinaryMessenger(super.createBinaryMessenger());
}
}
看源码中我们知道默认走的是系统的DefaultBinaryMessenger。
我们先看源码
class _DefaultBinaryMessenger extends BinaryMessenger {
const _DefaultBinaryMessenger._();
@override
Future<void> handlePlatformMessage(
String channel,
ByteData? message,
ui.PlatformMessageResponseCallback? callback,
) async {
ui.channelBuffers.push(channel, message, (ByteData? data) {
if (callback != null)
callback(data);
});
}
@override
Future<ByteData?> send(String channel, ByteData? message) {
final Completer<ByteData?> completer = Completer<ByteData?>();
// ui.PlatformDispatcher.instance is accessed directly instead of using
// ServicesBinding.instance.platformDispatcher because this method might be
// invoked before any binding is initialized. This issue was reported in
// #27541. It is not ideal to statically access
// ui.PlatformDispatcher.instance because the PlatformDispatcher may be
// dependency injected elsewhere with a different instance. However, static
// access at this location seems to be the least bad option.
// TODO(ianh): Use ServicesBinding.instance once we have better diagnostics
// on that getter.
ui.PlatformDispatcher.instance.sendPlatformMessage(channel, message, (ByteData? reply) {
try {
completer.complete(reply);
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: ErrorDescription('during a platform message response callback'),
));
}
});
return completer.future;
}
@override
void setMessageHandler(String channel, MessageHandler? handler) {
if (handler == null) {
ui.channelBuffers.clearListener(channel);
} else {
ui.channelBuffers.setListener(channel, (ByteData? data, ui.PlatformMessageResponseCallback callback) async {
ByteData? response;
try {
response = await handler(data);
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: ErrorDescription('during a platform message callback'),
));
} finally {
callback(response);
}
});
}
}
}
这个也是实现了BinaryMessenger的方法,那我们的思路就是在默认方法中拦截并调用自己的方法
final Map<String, MessageHandler> _outboundHandlers = <String, MessageHandler>{};
@override
void setMessageHandler(String channel, MessageHandler? handler) {
if (handler != null && handler.toString().contains("_textInputHanlde")) {
_outboundHandlers[channel] = handler;
return;
}...
当含有_textInputHanlde的时候,将处理方法改成自己的,然后再send的时候调用。
@override
Future<ByteData?> send(String channel, ByteData? message) {
final Completer<ByteData?> completer = Completer<ByteData?>();
final Future<ByteData?>? resultFuture;
final MessageHandler? handler = _outboundHandlers[channel];
if (handler != null) {
resultFuture = handler(message);
return resultFuture!;
}...
这样就实现了拦截。
二。使用
在Main函数中,runApp()之前调用以下方法
MyWidgetsFlutterBinding.ensureInitialized();
附属源码:
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'dart:ui' as ui;
class MyWidgetsFlutterBinding extends WidgetsFlutterBinding with MyServicesBinding {
static WidgetsBinding? ensureInitialized() {
MyWidgetsFlutterBinding();
return WidgetsBinding.instance;
}
}
mixin MyServicesBinding on BindingBase, ServicesBinding {
@override
BinaryMessenger createBinaryMessenger() {
return TestDefaultBinaryMessenger(super.createBinaryMessenger());
}
}
class TestDefaultBinaryMessenger extends BinaryMessenger {
final BinaryMessenger origin;
TestDefaultBinaryMessenger(this.origin);
final Map<String, MessageHandler> _outboundHandlers = <String, MessageHandler>{};
@override
Future<ByteData?> send(String channel, ByteData? message) {
final Completer<ByteData?> completer = Completer<ByteData?>();
final Future<ByteData?>? resultFuture;
final MessageHandler? handler = _outboundHandlers[channel];
if (handler != null) {
resultFuture = handler(message);
return resultFuture!;
}
ui.PlatformDispatcher.instance.sendPlatformMessage(channel, message, (ByteData? reply) {
try {
completer.complete(reply);
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: ErrorDescription('during a platform message response callback'),
));
}
});
return completer.future;
}
@override
void setMessageHandler(String channel, MessageHandler? handler) {
if (handler != null && handler.toString().contains("_textInputHanlde")) {
_outboundHandlers[channel] = handler;
return;
}
if (handler == null) {
ui.channelBuffers.clearListener(channel);
} else {
ui.channelBuffers.setListener(channel, (ByteData? data, ui.PlatformMessageResponseCallback callback) async {
ByteData? response;
try {
response = await handler(data);
} catch (exception, stack) {
FlutterError.reportError(FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'services library',
context: ErrorDescription('during a platform message callback'),
));
} finally {
callback(response);
}
});
}
}
@override
Future<void> handlePlatformMessage(
String channel,
ByteData? message,
ui.PlatformMessageResponseCallback? callback,
) async {
ui.channelBuffers.push(channel, message, (ByteData? data) {
if (callback != null) callback(data);
});
}
}
边栏推荐
- Multithreading et haute concurrence day09
- 国际标准ISO/IEC 30144: 2020在智能变电站辅助监测中的应用研究
- 9.5~10.5 GHz频段室内离体信道的测量与建模
- 盘一盘接口测试的那些痛点,你现在会解决了吗
- Web3 can't escape from the Wuzhishan of these old giants no matter how powerful it is
- Part 01: distributed registry
- Figure neural network driven traffic prediction technology: Exploration and challenge
- Go language concurrency and channel
- 一种基于随机接入时机动态分配的接入方案
- 【快速上手教程5】疯壳·开源编队无人机-飞控固件烧写
猜你喜欢
For() loop and quadratic for nesting of loop structure
Library management system based on jsp+servlet+mysql+bootstrap+css
不谈源码,聊聊位运算的实际应用
Go language concurrency and channel
Master slave replication of redis
电缆故障监测vr虚拟仿真教学软件的好处
引入 CloudWeGo 后飞书管理后台平台化改造的演进史
机器学习基础篇(4)滤波器
Bear pie bearpi HM_ Micro_ Hello of small_ World
[how to optimize her] teach you how to locate unreasonable SQL? And optimize her~~~
随机推荐
一种基于全相位FFT幅值的频率补偿方法
如何优雅的整合定时批量任务(荣耀典藏版)
Interpretation of gaitset source code (III)
【快速上手教程5】疯壳·开源编队无人机-飞控固件烧写
Redis' cache penetration, breakdown, avalanche
Force deduction ----- negative numbers in the statistical ordered matrix
Decentralized edge rendering metauniverse protocol how cadeus detonates metaverse summit 2022
CDH5、CDH6部署指南(稳)
JVM参数配置说明
工业厂区三维仿真可视化展示的应用
The evolution history of the background platform transformation of flybook management after the introduction of cloudwego
第02篇:分布式负载均衡
盘一盘接口测试的那些痛点,你现在会解决了吗
Research on Lora network security scheme based on RF fingerprint
SSM project integration [detailed]
Framework customization series (10) -- systemui customization status bar statusbar and navigation bar tutorial
【开发教程5】开源蓝牙心率防水运动手环-电池电量检测
JVM parameter configuration description
Bear pie bearpi HM_ Micro_ Hello of small_ World
我国智慧城市场景中物联网终端评测与认证体系研究