fix(animation): WASM 모드 안정성 개선

- SchedulerBinding으로 프레임 빌드 중 setState 방지
- persistentCallbacks 단계에서 addPostFrameCallback으로 지연 처리
This commit is contained in:
JiWoong Sul
2025-12-26 16:11:57 +09:00
parent 76d6bdc859
commit ee7dcd270e
2 changed files with 45 additions and 6 deletions

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:askiineverdie/data/race_data.dart'; import 'package:askiineverdie/data/race_data.dart';
import 'package:askiineverdie/src/core/animation/front_screen_animation.dart'; import 'package:askiineverdie/src/core/animation/front_screen_animation.dart';
@@ -45,7 +46,19 @@ class _HeroVsBossAnimationState extends State<HeroVsBossAnimation> {
_animationTimer = Timer.periodic( _animationTimer = Timer.periodic(
const Duration(milliseconds: frontScreenAnimationIntervalMs), const Duration(milliseconds: frontScreenAnimationIntervalMs),
(_) { (_) {
if (mounted) { if (!mounted) return;
// 프레임 빌드 중이면 다음 프레임까지 대기
if (SchedulerBinding.instance.schedulerPhase ==
SchedulerPhase.persistentCallbacks) {
SchedulerBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() {
_currentFrame =
(_currentFrame + 1) % frontScreenAnimationFrameCount;
});
}
});
} else {
setState(() { setState(() {
_currentFrame = _currentFrame =
(_currentFrame + 1) % frontScreenAnimationFrameCount; (_currentFrame + 1) % frontScreenAnimationFrameCount;
@@ -69,10 +82,23 @@ class _HeroVsBossAnimationState extends State<HeroVsBossAnimation> {
final allRaces = RaceData.all; final allRaces = RaceData.all;
if (allRaces.isEmpty) return; if (allRaces.isEmpty) return;
setState(() { // 프레임 빌드 중이면 다음 프레임까지 대기
_raceIndex = (_raceIndex + 1) % allRaces.length; if (SchedulerBinding.instance.schedulerPhase ==
_currentRaceId = allRaces[_raceIndex].raceId; SchedulerPhase.persistentCallbacks) {
}); SchedulerBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() {
_raceIndex = (_raceIndex + 1) % allRaces.length;
_currentRaceId = allRaces[_raceIndex].raceId;
});
}
});
} else {
setState(() {
_raceIndex = (_raceIndex + 1) % allRaces.length;
_currentRaceId = allRaces[_raceIndex].raceId;
});
}
} }
/// 글리치 효과: 랜덤 문자 대체 /// 글리치 효과: 랜덤 문자 대체

View File

@@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:askiineverdie/src/core/animation/character_frames.dart'; import 'package:askiineverdie/src/core/animation/character_frames.dart';
import 'package:askiineverdie/src/core/animation/race_character_frames.dart'; import 'package:askiineverdie/src/core/animation/race_character_frames.dart';
@@ -48,7 +49,19 @@ class _RacePreviewState extends State<RacePreview> {
void _startAnimation() { void _startAnimation() {
_timer = Timer.periodic(const Duration(milliseconds: 400), (_) { _timer = Timer.periodic(const Duration(milliseconds: 400), (_) {
if (mounted) { if (!mounted) return;
// 프레임 빌드 중이면 다음 프레임까지 대기 (WASM 모드 안정성)
if (SchedulerBinding.instance.schedulerPhase ==
SchedulerPhase.persistentCallbacks) {
SchedulerBinding.instance.addPostFrameCallback((_) {
if (mounted) {
setState(() {
_currentFrame++;
});
}
});
} else {
setState(() { setState(() {
_currentFrame++; _currentFrame++;
}); });