feat(perf): offload Android SMS parsing to Isolate and wrap pie chart with RepaintBoundary

This commit is contained in:
JiWoong Sul
2025-09-08 14:30:03 +09:00
parent 4673aed281
commit 10491af55b
2 changed files with 215 additions and 209 deletions

View File

@@ -10,6 +10,7 @@ import '../themed_text.dart';
import 'analysis_badge.dart';
import '../../l10n/app_localizations.dart';
import '../../providers/locale_provider.dart';
import '../../utils/reduce_motion.dart';
/// 구독 서비스 비율을 파이 차트로 보여주는 카드 위젯
class SubscriptionPieChartCard extends StatefulWidget {
@@ -312,58 +313,69 @@ class _SubscriptionPieChartCardState extends State<SubscriptionPieChartCard> {
);
}
return PieChart(
PieChartData(
borderData: FlBorderData(show: false),
sectionsSpace: 2,
centerSpaceRadius: 60,
sections:
_applyTouchedState(snapshot.data!),
pieTouchData: PieTouchData(
enabled: true,
touchCallback: (FlTouchEvent event,
pieTouchResponse) {
// 터치 응답이 없거나 섹션이 없는 경우
if (pieTouchResponse == null ||
pieTouchResponse.touchedSection ==
null) {
// 차트 밖으로 나갔을 때만 리셋
if (_touchedIndex != -1) {
setState(() {
_touchedIndex = -1;
});
return RepaintBoundary(
child: PieChart(
PieChartData(
borderData: FlBorderData(show: false),
sectionsSpace: 2,
centerSpaceRadius: 60,
sections:
_applyTouchedState(snapshot.data!),
pieTouchData: PieTouchData(
enabled: true,
touchCallback: (FlTouchEvent event,
pieTouchResponse) {
// 터치 응답이 없거나 섹션이 없는 경우
if (pieTouchResponse == null ||
pieTouchResponse
.touchedSection ==
null) {
// 차트 밖으로 나갔을 때만 리셋
if (_touchedIndex != -1) {
setState(() {
_touchedIndex = -1;
});
}
return;
}
return;
}
final touchedIndex = pieTouchResponse
.touchedSection!
.touchedSectionIndex;
final touchedIndex =
pieTouchResponse.touchedSection!
.touchedSectionIndex;
// 탭 이벤트 처리 (토글)
if (event is FlTapUpEvent) {
setState(() {
// 동일 섹션 탭하면 선택 해제, 아니면 선택
_touchedIndex = (_touchedIndex ==
touchedIndex)
? -1
: touchedIndex;
});
return;
}
// hover 이벤트 처리 (단순 표시)
if (event is FlPointerHoverEvent ||
event is FlPointerEnterEvent) {
// 현재 인덱스와 다른 경우만 업데이트
if (_touchedIndex != touchedIndex) {
// 탭 이벤트 처리 (토글)
if (event is FlTapUpEvent) {
setState(() {
_touchedIndex = touchedIndex;
// 동일 섹션 탭하면 선택 해제, 아니면 선택
_touchedIndex =
(_touchedIndex ==
touchedIndex)
? -1
: touchedIndex;
});
return;
}
}
},
// hover 이벤트 처리 (단순 표시)
if (event is FlPointerHoverEvent ||
event is FlPointerEnterEvent) {
// 현재 인덱스와 다른 경우만 업데이트
if (_touchedIndex !=
touchedIndex) {
setState(() {
_touchedIndex = touchedIndex;
});
}
}
},
),
),
swapAnimationDuration:
ReduceMotion.isEnabled(context)
? const Duration(milliseconds: 0)
: const Duration(
milliseconds: 300),
swapAnimationCurve: Curves.easeOut,
),
);
},