🦧
[Flutter] RiverpodのStateProviderの値をdebounceする方法
Before
例えば、RiverpodのStateProviderを使ったSliderのUIの実装は↓になります。
でも設定途中の値に関心がなくて、設定完了後の値のみ取得したいです。
final sliderProvider = StateProvider<double>((ref) => 0);
class MyHomePage extends ConsumerWidget {
const MyHomePage({Key? key}) : super(key: key);
Widget build(BuildContext context, WidgetRef ref) {
StateController<double> sliderState = ref.watch(sliderProvider.notifier);
final value = ref.watch(sliderProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
),
body: Column(
children: [
const Spacer(),
Slider(
value: value, onChanged: (event) => sliderState.state = event),
Text(value.toString()),
const Spacer(),
],
));
}
}
Goal
stateの値をdebounceします。
How
RxDartを使用します。
まずRxDartをimportします。
import 'package:rxdart/rxdart.dart';
Streamを定義します。
final sliderProvider = StateProvider<double>((ref) => 0);
// 1. ConsumerWidget -> ConsumerStatefulWidget
class MyHomePage extends ConsumerStatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
ConsumerState<ConsumerStatefulWidget> createState() => MyHomePageState();
}
class MyHomePageState extends ConsumerState<MyHomePage> {
// 2. StreamControllerを定義
final StreamController<double> _debounceChangesStream = StreamController();
StreamSubscription? _debounceChangesStreamSubscription;
String textValue = '';
void initState() {
super.initState();
// 4. streamをRxDartのdebounce operatorを使います。
_debounceChangesStreamSubscription = _debounceChangesStream.stream
.debounceTime(const Duration(seconds: 1))
.listen((event) {
setState(() {
textValue = event.toString();
});
});
}
Widget build(BuildContext context) {
StateController<double> sliderState = ref.watch(sliderProvider.notifier);
final value = ref.watch(sliderProvider);
// 3. stateの変更をstreamに入れる。
ref.listen<double>(
sliderProvider, ((previous, next) => _debounceChangesStream.add(next)));
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo Home Page'),
),
body: Column(
children: [
const Spacer(),
Slider(
value: value, onChanged: (event) => sliderState.state = event),
Text(textValue),
const Spacer(),
],
));
}
void dispose() {
_debounceChangesStreamSubscription?.cancel();
super.dispose();
}
}
After
もしほかに方法もある場合ぜひ教えてください! :]
Discussion