본문 바로가기
Mobile APP/Flutter

[Flutter] 중복 클릭 방지 버튼, StreamController, Throttle 버튼 구현

by 흐암졸령 2022. 12. 7.
반응형

문제 상황

 버튼을 만들고, api 에 연결하는 것은 흔히 있는 일이다. 그러나 버튼을 연속적으로 클릭해서 api 호출이 여러번 일어나면 예상하지 못 한 사이트 이펙트가 일어나게 된다. 보통 버튼을 클릭하면 Navigator.pop() 과 같이 다른 페이지로 이동하거나 하지만, 매우 빠르게 클릭하면 중복으로 처리가 되는 문제가 있다.

 

해결 방법

 중복 클릭과 같은 문제에 대해서는 두 가지 방법이 있다. Throttle과 Debounce이다. 둘에 대한 설명으로는 다음 포스팅을 보면 자세하게 나와있다.

 

혼란한 디바운스(debounce)와 스로틀(throttle) 차이

scroll, resize, input, mousemove 와 같은 이벤트는 짧은 시간 간격으로 연속해서 발생합니다.이러한 이벤트에 바인딩한 이벤트 핸들러는 과도하게 호출되어 성능에 문제를 일으킬 수 있습니다.버튼을

velog.io

 

 이번 포스팅에서는 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,
        );
      },
    );
  }
}

 

다른 방법

 

[flutter]throttle, debounce 만들기, 구현 예제 by Dart

다른 언어로 프론트 개발을 해봤다면 이미 사용해봤거나 개념 정도는 익히고 있겠지만 flutter 그리고 Dart가 첫 개발 언어이신 분들을 위해 간단히 요약하자면throttle ➡️ 지정된 시간동안 연속

velog.io

이번 포스팅에서는 Stream 을 사용해서 로직을 만들었지만, 클릭을 한 시점부터 Timer 를 사용해서 throttle 을 구현할 수도 있다.

반응형

댓글