Flutter—— 一个有意思的工具:行为录制器 behavior_recorder
前言
此工具提供用户行为(手势
、文字输入
)的录制及回放,同时支持记录的导出和导入。
例如,可以由测试人员进行bug复现步骤
的录制及上传,并由对应开发人员下载导出再重放。当然也可以用于线上用户的反馈。
Tip:
1.此工具目前支持 flutter 2.5.3-null-safety,
->如果是其他版本的flutter可以查看Beike_AspectD是否支持,或者自行fork进行相关适配即可
2.动图可能有点儿大。
行为的录制和回放
行为记录的导出、导入及回放
实现
两种行为的录制都是基于hook实现的, 这里做一下简单介绍。
手势录制及回放
录制
手势的录制通过hook GestureBinding
的-handlePointerEvent
方法,对平台端所传递过来的pointer event
进行转换并生成PointerEventBundle
存储在队列中。
void _hookHandlePointerEvent(PointCut pointCut) {
gestureRecorder.handleHook(pointCut);
pointCut.proceed();
}
class GestureRecorder extends Recorder<PointerEventBundle>{
///...其它代码
@override
void handleHook(PointCut pointCut) {
if(pointCut.positionalParams.isEmpty) {
return;
}
startTime ??= timeStamp;
final event = pointCut.positionalParams.first;
_cacheBucket.add(event);
if(event is PointerUpEvent || event is PointerCancelEvent) {
final int endTime = DateTime.now().millisecondsSinceEpoch;
enqueue(PointerEventBundle.load(startTime!, endTime, type, Queue.from(_cacheBucket)));
startTime = null;
_cacheBucket.clear();
}
}
@override
SourceType get type => SourceType.gesture;
}
回放
PointerEventBundle
内部存储原始的pointer event(队列形式)
,只需将它们按序传递给GestureBinding
的handlePointerEvent
方法即可实现回放。
@override
Future perform() async {
while(_eventQueue.isNotEmpty) {
await WidgetsBinding.instance?.endOfFrame;
GestureBinding.instance?.handlePointerEvent(_eventQueue.removeFirst());
}
return Future.value();
}
文字输入的录制和回放
录制
文字输入的录制是通过hookTextInput
的 _handleTextInputInvocation
方法,对平台端所传递的文字输入事件
进行转换,并生成TextInputEventBundle
存储在队列中。
class TextInputRecorder extends Recorder<TextInputEventBundle> {
///...其它代码
@override
void handleHook(PointCut pointCut) {
if(pointCut.positionalParams.isEmpty) {
return;
}
final int startTime = DateTime.now().millisecondsSinceEpoch;
final methodCall = pointCut.positionalParams.first;
if(methodCall is MethodCall && methodCall.arguments is List) {
final list = methodCall.arguments as List;
if(list.isNotEmpty) {
id = list.first;
}
}
final int endTime = DateTime.now().millisecondsSinceEpoch;
enqueue(TextInputEventBundle(startTime, endTime, type, methodCall));
}
}
回放
文字输入事件
的回放与上面大致相同:
1. 首先我们将`TextInputEventBundle`内部存储的事件对象,
通过SystemChannels.textInput.codec编码器转化为 bytedata
2. 之后,将bytedata交给ServicesBinding.instance?
.defaultBinaryMessenger
.handlePlatformMessage方法即可
@override
Future perform() async {
_updateRecord();
final bytedata = SystemChannels.textInput.codec.encodeMethodCall(methodCall);
ServicesBinding.instance?.defaultBinaryMessenger
.handlePlatformMessage(SystemChannels.textInput.name, bytedata, null);
return Future.value();
}
功能介绍
首先添加 import 'package:behavior_recorder_of_kit/behavior_recorder_of_kit.dart';
到main.dart
文件。
录制和播放
通过 RecordPlayer().startRecord()
开始录制,以及RecordPlayer().finishRecord()
结束录制。
录制结束后,通过 RecordPlayer().play();
进行重播。
Tip: 所录制的行为事件是一次性的,即:在播放后将会失效。
如果需要重复播放,可以考虑通过RecordPlayer().exportTape()将事件导出。
记录的导出和导入
如果需要将录制的记录导出,可以通过 RecordPlayer().exportTape()
方法。
Tip: 导出后的序列化方式需要自行定义。
当我们需要从外部导入行为记录时,可以通过 RecordPlayer().loadRecords();
方法:
//导入录制前,要开启录制功能
RecordPlayer().startRecord();
while(cache.isNotEmpty) {
RecordPlayer().loadRecords(cache.removeFirst());
}
//结束导入后,建议关闭录制。
RecordPlayer().finishRecord();
//之后通过下方法即可播放记录。
RecordPlayer().play()
其它用法,可以见项目的Readme
, 谢谢阅读。
项目地址:
其它文章
转载自:https://juejin.cn/post/7105948915522633736