Skip to content

Commit 4de0f75

Browse files
committed
refactor: remove stream_transform package
1 parent 786731e commit 4de0f75

File tree

6 files changed

+145
-33
lines changed

6 files changed

+145
-33
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
> [!IMPORTANT]
44
> See the [Migration Guides](https://amoshuke.github.io/flutter_tilt_book/en/docs/migration-guides/) for the details of breaking changes between versions.
55
6+
## 3.3.3 (Unreleased)
7+
8+
**Improvements**
9+
10+
- Remove stream_transform package.
11+
612
## 3.3.2
713

814
**Improvements**

example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ dependencies:
3636

3737
# The following adds the Cupertino Icons font to your application.
3838
# Use with the CupertinoIcons class for iOS style icons.
39-
cupertino_icons: ^1.0.8
39+
cupertino_icons: ^1.0.9
4040

4141
dev_dependencies:
4242
flutter_test:

lib/src/internal/controllers/tilt_gestures_controller.dart

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import 'package:flutter/services.dart' show DeviceOrientation;
33
import 'package:flutter/widgets.dart';
44

55
import 'package:sensors_plus/sensors_plus.dart';
6-
import 'package:stream_transform/stream_transform.dart';
76

87
import '../../config/tilt_config.dart';
98
import '../../enums.dart';
@@ -56,6 +55,15 @@ class TiltGesturesController {
5655
/// 手势协调器
5756
async.Timer? _gesturesHarmonizerTimer;
5857

58+
/// 陀螺仪采样定时器
59+
async.Timer? _gyroscopeSamplingTimer;
60+
61+
/// 是否已完成传感器订阅初始化
62+
bool _sensorsInitialized = false;
63+
64+
/// 最近一帧可用于补帧/限流的陀螺仪数据
65+
TiltStreamModel? _pendingGyroscopeTiltStreamModel;
66+
5967
/// 是否开启 TiltStream
6068
bool get enableTiltStream => !disable;
6169

@@ -65,6 +73,7 @@ class TiltGesturesController {
6573

6674
void dispose() {
6775
cancelGesturesHarmonizerTimer();
76+
cancelGyroscopeSamplingTimer();
6877
cancelAllSubscriptions();
6978
}
7079

@@ -74,12 +83,20 @@ class TiltGesturesController {
7483
_gesturesHarmonizerTimer = null;
7584
}
7685

86+
/// 取消陀螺仪采样定时器(补帧/限流)
87+
void cancelGyroscopeSamplingTimer() {
88+
_gyroscopeSamplingTimer?.cancel();
89+
_gyroscopeSamplingTimer = null;
90+
_pendingGyroscopeTiltStreamModel = null;
91+
}
92+
7793
/// 取消所有订阅
7894
void cancelAllSubscriptions() {
7995
for (final sub in streamSubscriptions) {
8096
sub.cancel();
8197
}
8298
streamSubscriptions.clear();
99+
_sensorsInitialized = false;
83100
}
84101

85102
/// 过滤 TiltStream
@@ -197,11 +214,14 @@ class TiltGesturesController {
197214
/// 初始化传感器
198215
void initSensors(BuildContext context) {
199216
if (!_canSensorsPlatformSupport ||
217+
_sensorsInitialized ||
200218
!enableTiltStream ||
201219
!tiltConfig.enableGestureSensors) {
202220
return;
203221
}
204222

223+
_sensorsInitialized = true;
224+
205225
/// 订阅设备方向事件
206226
subscribeToDeviceOrientation(context);
207227

@@ -211,32 +231,46 @@ class TiltGesturesController {
211231

212232
/// 订阅陀螺仪倾斜事件
213233
void subscribeToGyroscopeTilt() {
234+
final frameDuration = Duration(milliseconds: (1000 / fps) ~/ 1);
235+
214236
streamSubscriptions.add(
215-
gyroscopeEventStream()
216-
.map<TiltStreamModel>(
217-
(GyroscopeEvent gyroscopeEvent) => TiltStreamModel(
218-
position: Offset(gyroscopeEvent.y, gyroscopeEvent.x),
219-
gesturesType: GesturesType.sensors,
220-
gestureUse: true,
221-
),
222-
)
223-
.combineLatest(
224-
Stream<void>.periodic(Duration(milliseconds: (1000 / fps) ~/ 1)),
225-
(p0, _) => p0,
226-
)
227-
.throttle(Duration(milliseconds: (1000 / fps) ~/ 1), trailing: true)
228-
.listen(
229-
(TiltStreamModel tiltStreamModel) {
230-
if (tiltStreamController.hasListener) {
231-
tiltStreamController.sink.add(tiltStreamModel);
232-
}
237+
gyroscopeEventStream().listen(
238+
(GyroscopeEvent gyroscopeEvent) {
239+
_pendingGyroscopeTiltStreamModel = TiltStreamModel(
240+
position: Offset(gyroscopeEvent.y, gyroscopeEvent.x),
241+
gesturesType: GesturesType.sensors,
242+
gestureUse: true,
243+
);
244+
245+
/// 如果陀螺仪存在数据,则开启陀螺仪采样定时器(补帧/限流)
246+
_gyroscopeSamplingTimer ??= async.Timer.periodic(
247+
frameDuration,
248+
(_) => _pushLatestGyroscopeTiltStreamModel(),
249+
);
250+
},
251+
onError: (_) {
252+
_canSensorsPlatformSupport = false;
253+
cancelGyroscopeSamplingTimer();
233254
},
234-
onError: (_) => _canSensorsPlatformSupport = false,
235255
cancelOnError: true,
236256
),
237257
);
238258
}
239259

260+
/// 按帧推送当前缓存的最新陀螺仪值,用于补帧和限流
261+
void _pushLatestGyroscopeTiltStreamModel() {
262+
if (!tiltStreamController.hasListener) {
263+
cancelGyroscopeSamplingTimer();
264+
return;
265+
}
266+
267+
final tiltStreamModel = _pendingGyroscopeTiltStreamModel;
268+
269+
if (tiltStreamModel != null) {
270+
tiltStreamController.sink.add(tiltStreamModel);
271+
}
272+
}
273+
240274
/// 订阅设备方向事件
241275
void subscribeToDeviceOrientation(BuildContext context) {
242276
streamSubscriptions.add(

lib/src/widgets/tilt_stream_builder.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ class _TiltStreamBuilderState extends State<TiltStreamBuilder> {
4040
super.dispose();
4141
}
4242

43+
@override
44+
void didUpdateWidget(TiltStreamBuilder oldWidget) {
45+
super.didUpdateWidget(oldWidget);
46+
if (oldWidget.tiltGesturesController != widget.tiltGesturesController) {
47+
oldWidget.tiltGesturesController.dispose();
48+
widget.tiltGesturesController.initSensors(context);
49+
}
50+
}
51+
4352
@override
4453
Widget build(BuildContext context) {
4554
return StreamBuilder<TiltStreamModel>(

pubspec.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ description: Easily apply tilt parallax hover effects for Flutter, which support
88
# https://semver.org/spec/v2.0.0-rc.1.html
99
# https://dart.dev/tools/pub/versioning#semantic-versions
1010
# https://dart.dev/tools/pub/dependencies#version-constraints
11-
version: 3.3.2
11+
version: 3.3.3
1212
homepage: https://amoshuke.github.io/flutter_tilt_book
1313
repository: https://github.com/fluttercandies/flutter_tilt
1414
issue_tracker: https://github.com/fluttercandies/flutter_tilt/issues
@@ -27,7 +27,6 @@ environment:
2727
dependencies:
2828
flutter:
2929
sdk: flutter
30-
stream_transform: ^2.1.0
3130
sensors_plus: '>=6.1.0 <8.0.0'
3231

3332
dev_dependencies:

test/internal/controllers/tilt_gestures_controller_test.dart

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ void main() {
2121
late TiltGesturesController controller;
2222
late TiltConfig tiltConfig;
2323
late Offset initialPosition;
24+
late int frameDurationMs;
2425

2526
setUp(() {
2627
tiltStreamController = StreamController<TiltStreamModel>.broadcast();
@@ -37,6 +38,7 @@ void main() {
3738
tiltConfig: tiltConfig,
3839
initialPosition: initialPosition,
3940
);
41+
frameDurationMs = (1000 / controller.fps) ~/ 1;
4042
});
4143

4244
tearDown(() {
@@ -55,6 +57,9 @@ void main() {
5557
testWidgets('Sensors stream subscriptions', (WidgetTester tester) async {
5658
var currentGesturesType = GesturesType.none;
5759
var currentPosition = Offset.zero;
60+
var sensorFrameCount = 0;
61+
var replayedFrameCount = 0;
62+
late StreamSubscription<TiltStreamModel> firstSubscription;
5863

5964
debugDefaultTargetPlatformOverride = TargetPlatform.android;
6065

@@ -81,28 +86,49 @@ void main() {
8186

8287
await tester.runAsync(
8388
() async {
89+
firstSubscription = tiltStreamController.stream.listen(
90+
(TiltStreamModel tiltStreamModel) {
91+
currentPosition = tiltStreamModel.position;
92+
currentGesturesType = tiltStreamModel.gesturesType;
93+
if (tiltStreamModel.gesturesType == GesturesType.sensors) {
94+
sensorFrameCount++;
95+
}
96+
},
97+
);
98+
8499
await tester.pumpWidget(
85100
Builder(
86101
builder: (BuildContext context) {
87-
/// 监听数据
88-
tiltStreamController.stream.listen(
89-
(TiltStreamModel tiltStreamModel) {
90-
currentPosition = tiltStreamModel.position;
91-
currentGesturesType = tiltStreamModel.gesturesType;
92-
},
93-
);
94-
95102
/// 初始化传感器
96103
controller.initSensors(context);
97104
return const SizedBox();
98105
},
99106
),
100107
);
101108

102-
/// 延迟 1 帧,等待数据
109+
/// 延迟 3 帧,等待数据 sensorFrameCount 累加到 3
103110
await Future.delayed(
104-
Duration(milliseconds: (1000 / controller.fps) ~/ 1),
111+
Duration(milliseconds: frameDurationMs * 3),
105112
);
113+
114+
/// 取消订阅后,等待 2 帧,确保没有更多数据到达
115+
await firstSubscription.cancel();
116+
await Future.delayed(
117+
Duration(milliseconds: frameDurationMs * 2),
118+
);
119+
120+
/// 由于没有更多陀螺仪数据到达,replayedFrameCount 应该保持为 0
121+
final replaySubscription = tiltStreamController.stream.listen(
122+
(TiltStreamModel tiltStreamModel) {
123+
if (tiltStreamModel.gesturesType == GesturesType.sensors) {
124+
replayedFrameCount++;
125+
}
126+
},
127+
);
128+
await Future.delayed(
129+
Duration(milliseconds: frameDurationMs * 2),
130+
);
131+
await replaySubscription.cancel();
106132
},
107133
);
108134

@@ -111,6 +137,8 @@ void main() {
111137
currentPosition,
112138
Offset(gyroscopeSensorData.last[1], gyroscopeSensorData.last[0]),
113139
);
140+
expect(sensorFrameCount, 3);
141+
expect(replayedFrameCount, 0);
114142
expect(controller.streamSubscriptions.length, 2);
115143

116144
/// 取消订阅
@@ -120,6 +148,42 @@ void main() {
120148
debugDefaultTargetPlatformOverride = null;
121149
});
122150

151+
testWidgets('initSensors only subscribes once',
152+
(WidgetTester tester) async {
153+
debugDefaultTargetPlatformOverride = TargetPlatform.android;
154+
155+
SensorsMock.initMockSensorsMethodChannel([
156+
SensorsMock.accelerometerMethodName,
157+
SensorsMock.gyroscopeMethodName,
158+
]);
159+
final date = DateTime.now();
160+
SensorsMock.initMockSensorChannelData(
161+
SensorsMock.accelerometerChannelName,
162+
<List<double>>[
163+
[1.0, 2.0, 3.0, date.microsecondsSinceEpoch.toDouble()],
164+
],
165+
);
166+
SensorsMock.initMockSensorChannelData(
167+
SensorsMock.gyroscopeChannelName,
168+
<List<double>>[
169+
[3.0, 4.0, 5.0, date.microsecondsSinceEpoch.toDouble()],
170+
],
171+
);
172+
173+
await tester.pumpWidget(
174+
Builder(
175+
builder: (BuildContext context) {
176+
controller.initSensors(context);
177+
controller.initSensors(context);
178+
return const SizedBox();
179+
},
180+
),
181+
);
182+
183+
expect(controller.streamSubscriptions.length, 2);
184+
debugDefaultTargetPlatformOverride = null;
185+
});
186+
123187
test('Tilt stream updates (sensors)', () async {
124188
const deviceOrientationList = DeviceOrientation.values;
125189
const testModel = TiltStreamModel(

0 commit comments

Comments
 (0)