Flutter—— 一個有意思的工具:行為錄製器 behavior_recorder

語言: CN / TW / HK

theme: smartblue

我正在參加跨端技術專題徵文活動,詳情檢視:juejin.cn/post/710123…

前言

此工具提供使用者行為(手勢文字輸入)的錄製及回放,同時支援記錄的匯出和匯入。

例如,可以由測試人員進行bug復現步驟的錄製及上傳,並由對應開發人員下載匯出再重放。當然也可以用於線上使用者的反饋。

Tip:

1.此工具目前支援 flutter 2.5.3-null-safety,

->如果是其他版本的flutter可以檢視Beike_AspectD是否支援,或者自行fork進行相關適配即可

2.動圖可能有點兒大。

行為的錄製和回放

行為錄製和回放

行為記錄的匯出、匯入及回放

錄製的匯出和匯入以及回放.gif

實現

兩種行為的錄製都是基於hook實現的, 這裡做一下簡單介紹。

手勢錄製及回放

錄製

手勢的錄製通過hook GestureBinding-handlePointerEvent方法,對平臺端所傳遞過來的pointer event進行轉換並生成PointerEventBundle 儲存在佇列中。

void _hookHandlePointerEvent(PointCut pointCut) { gestureRecorder.handleHook(pointCut); pointCut.proceed(); }

``` class GestureRecorder extends Recorder{

///...其它程式碼

@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(佇列形式),只需將它們按序傳遞給GestureBindinghandlePointerEvent方法即可實現回放。

@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 {

///...其它程式碼

@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, 謝謝閱讀。

專案地址:

behavior_recorder

其它文章

Flutter&Flame在遊戲上的實踐——坦克大戰

【翻譯】識別&處理Android構建時的記憶體問題

Flutter——原生View的Touch事件分發流程

Flutter在Android平臺上啟動時,Native層做了什麼?

Flutter 仿同花順自選股列表