[Flutter] timer 예제

Flutter에서 Timer 클래스는 Dart의 dart:async 라이브러리에 정의되어 있으며, 시간 기반의 작업을 스케줄링하는 데 사용됩니다. Timer를 사용하여 단일 시간 지연 후에 작업을 실행하거나, 주기적인 간격으로 반복 작업을 수행할 수 있습니다. 타이머 예제 두 가지를 통해서 사용하는 방법을 알아보겠습니다!

Timer의 주요 기능

일회성 타이머 (Timer): 지정된 시간이 경과한 후에 단 한 번 작업을 수행합니다.

Timer(Duration(seconds: 5), () {
  // 5초 후에 실행될 코드
});

주기적 타이머 (Timer.periodic): 지정된 간격으로 반복적으로 작업을 수행합니다.

Timer.periodic(Duration(seconds: 5), (Timer t) {
  // 매 5초마다 반복적으로 실행될 코드
});

Timer 사용시 고려사항

  • 생명주기 관리: Timer는 앱의 생명주기와 독립적으로 작동합니다. 따라서 위젯이 소멸되거나 더 이상 필요하지 않을 때 Timer를 적절히 취소해야 합니다. 이를 위해 Timer 객체를 저장하고, 위젯이 소멸될 때 (dispose 메서드 내에서) Timer를 취소하는 것이 좋습니다.
  • 백그라운드 상태: Flutter 앱이 백그라운드로 이동하면, 타이머의 동작은 플랫폼(iOS/Android)에 따라 다를 수 있습니다. 특히 iOS에서는 백그라운드 상태에서 타이머가 일시중지되거나 작동하지 않을 수 있습니다.
  • 성능과 자원: 주기적인 타이머는 추가적인 시스템 자원을 사용하므로, 자원 사용을 최적화하기 위해 필요할 때만 타이머를 사용하는 것이 중요합니다.

타이머 예제 1

import 'dart:async';
import 'package:flutter/material.dart';

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  Timer? _timer;

  @override
  void initState() {
    super.initState();
    _timer = Timer.periodic(Duration(seconds: 5), (Timer t) {
      // 주기적으로 실행될 작업
    });
  }

  @override
  void dispose() {
    _timer?.cancel(); // 타이머 취소
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // UI 구성
  }
}

이 예제에서 _timer는 5초마다 반복적으로 작업을 수행하는 주기적 타이머입니다. dispose 메서드에서 타이머를 취소하여 위젯이 소멸될 때 자원을 해제합니다. 이러한 방식으로 Timer를 사용하면 효과적으로 시간 기반 작업을 스케줄링할 수 있습니다.

타이머 예제2

Flutter 앱에서 백그라운드로 이동할 때 타이머를 멈추고 싶다면, WidgetsBindingObserver를 사용하여 앱의 생명주기 상태를 감지하고 그에 따라 타이머를 시작하거나 중지할 수 있습니다. WidgetsBindingObserver는 앱이 포그라운드로 이동하거나 백그라운드로 이동하는 것을 감지할 수 있으며, 이를 통해 타이머의 동작을 제어할 수 있습니다.

다음은 WidgetsBindingObserver를 사용하여 백그라운드로 이동할 때 타이머를 멈추고, 다시 포그라운드로 돌아왔을 때 타이머를 재시작하는 방법을 보여주는 코드 예시입니다:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class PremiumController extends GetxController with WidgetsBindingObserver {
  Timer? _periodicTimer;

  @override
  void onInit() {
    super.onInit();
    WidgetsBinding.instance.addObserver(this); // 옵저버 추가
    _startTimer(); // 타이머 시작
  }

  @override
  void onClose() {
    _stopTimer(); // 타이머 정리
    WidgetsBinding.instance.removeObserver(this); // 옵저버 제거
    super.onClose();
  }

  void _startTimer() {
    _periodicTimer = Timer.periodic(Duration(minutes: 1), (Timer t) {
      updateAccessStatus();
    });
  }

  void _stopTimer() {
    _periodicTimer?.cancel();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      // 앱이 포그라운드로 돌아왔을 때
      _startTimer();
    } else if (state == AppLifecycleState.paused) {
      // 앱이 백그라운드로 이동했을 때
      _stopTimer();
    }
  }

  void updateAccessStatus() {
    // ... 상태 업데이트 로직 ...
  }
}

위 코드에서는 WidgetsBindingObserver를 구현하여 앱의 생명주기 상태 변화를 감지합니다. didChangeAppLifecycleState 메서드는 앱의 상태가 변경될 때 호출되며, 이를 통해 타이머를 제어할 수 있습니다. 앱이 백그라운드로 이동(paused)할 때 타이머를 중지하고, 다시 포그라운드(resumed)로 돌아올 때 타이머를 재시작합니다.

이렇게 하면 앱이 백그라운드에서는 타이머를 멈추고, 포그라운드로 돌아올 때 필요한 작업을 계속할 수 있게 됩니다.