반응형
문제 상황
버튼을 만들고, api 에 연결하는 것은 흔히 있는 일이다. 그러나 버튼을 연속적으로 클릭해서 api 호출이 여러번 일어나면 예상하지 못 한 사이트 이펙트가 일어나게 된다. 보통 버튼을 클릭하면 Navigator.pop() 과 같이 다른 페이지로 이동하거나 하지만, 매우 빠르게 클릭하면 중복으로 처리가 되는 문제가 있다.
해결 방법
중복 클릭과 같은 문제에 대해서는 두 가지 방법이 있다. Throttle과 Debounce이다. 둘에 대한 설명으로는 다음 포스팅을 보면 자세하게 나와있다.
이번 포스팅에서는 Stream을 사용해서 Throttle을 구현하려 한다. 대략적인 느낌은 stream에 값으로 bool 값을 들고 있는데. 이 값이 true 일 때만 버튼이 눌러진다. 그리고 버튼이 눌러지면 어느정도의 시간동안 false 의 값으로 변했다가 다시 true로 바뀐다.
아래의 코드에서는 500ms 동안 false로 바뀌어있는데, 주어진 onTap 함수를 끝낼 때 true로 바꾸는 식으로 해도 된다.
import 'dart:async';
import 'package:flutter/material.dart';
class ThrottleInkWell extends StatefulWidget {
const ThrottleInkWell({
Key? key,
this.onTap,
required this.child,
}) : super(key: key);
final GestureTapCallback? onTap;
final Widget child;
@override
State<ThrottleInkWell> createState() => _ThrottleInkWellState();
}
class _ThrottleInkWellState extends State<ThrottleInkWell> {
late StreamController<bool> _btnController;
@override
void initState() {
super.initState();
_btnController = StreamController<bool>();
}
@override
void dispose() {
_btnController.close();
super.dispose();
}
void _btnOnTap() {
if (_btnController.isClosed) return;
_btnController.add(false);
Future<void>.delayed(const Duration(milliseconds: 500), () {
if (_btnController.isClosed) return;
_btnController.add(true);
});
widget.onTap?.call();
}
@override
Widget build(BuildContext context) {
return StreamBuilder<bool>(
initialData: true,
stream: _btnController.stream,
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
return InkWell(
onTap: snapshot.data ?? true ? _btnOnTap : null,
child: widget.child,
);
},
);
}
}
다른 방법
이번 포스팅에서는 Stream 을 사용해서 로직을 만들었지만, 클릭을 한 시점부터 Timer 를 사용해서 throttle 을 구현할 수도 있다.
반응형
'Mobile APP > Flutter' 카테고리의 다른 글
[Flutter] Custom Paint Border Radius 있는 rect 그리기 (0) | 2023.02.15 |
---|---|
[Flutter] M1 pod install 'CocoaPods could not find compatible versions for pod "FBAudienceNetwork"' 해결 (0) | 2023.01.28 |
[Flutter] Flutter로 개발하면서 느낀 점 (0) | 2022.06.11 |
[Flutter] AVOID using forEach with a function literal 해결하기 (0) | 2022.02.07 |
[Flutter] A RenderFlex overflowed by pixels on the bottom 에러 해결 (0) | 2022.02.02 |
댓글