가계부앱을 만들 때 매출과 지출을 RederList를 사용하여서 매출과 지출의 순서를 변경 할 수 있게 코드를 짰습니다.
그리고 그 매출 카테고리에 따른 값들이 보이고, 지출에 따른 카테고리 값들이 보이게 했습니다.
각 카테고리 값들이 처음 선택 했을 때는 문제 없이 돌아갔지만, 실수로 누른 값을 다시 수정 할 때 카테고리의 값이 초기 값으로 변환되는 문제가 발생하였습니다.
그 과정을 해결하는 글 입니다.
문제 상황
매출(수입)에서 현금을 선택한 후, 지출로 전환하여 광고비를 선택했을 때 여전히 현금이 표시되는 문제가 발생했습니다. 이는 카테고리 전환 시 값이 제대로 업데이트되지 않기 때문이었습니다.
원인 분석
- 컨트롤러의 상태 관리 문제: MoneyTrackerInputController의 changeIncomeType 메서드에서 타입 변경 시 반대 타입의 카테고리 값을 초기화하지 않았습니다.
- 위젯에서의 상태 관리 문제: IncomeExpenseSelectWidget에서 타입 전환 시 카테고리 값이 제대로 초기화되지 않았습니다.
- 저장된 값 관리 문제: 타입 전환 시 이전에 저장된 카테고리 값이 계속 유지되어 문제가 발생했습니다.
ReorderList에서 현재 인덱스에 있는 타입을 명확히 하게 할 것
onReorder: (oldIndex, newIndex) {
if (newIndex > oldIndex) {
newIndex -= 1;
}
final item = items.removeAt(oldIndex);
items.insert(newIndex, item);
_saveOrder();
// 순서 변경 후 첫 번째 항목을 활성화
Future.microtask(() {
final newType = items[0]['type'] as IncomeType;
// 타입 변경 전에 현재 타입 확인
if (controller.incomeType.value != newType) {
// 타입 변경
controller.changeIncomeType(newType);
// 타입에 따라 카테고리 값 명확하게 설정
// (동일한 로직 적용)
}
});
}
해당 타입을 변수로 받기
// 수정 전
void changeIncomeType(IncomeType type) {
incomeType.value = type;
// 타입 변경 시 해당 타입의 카테고리가 비어있으면 기본값 설정
if (type == IncomeType.income && selectedCategory1.value.isEmpty) {
if (incomeCategories.isNotEmpty) {
selectedCategory1.value = incomeCategories.first;
}
} else if (type == IncomeType.expense && selectedCategoryE1.value.isEmpty) {
if (expenseCategories.isNotEmpty) {
selectedCategoryE1.value = expenseCategories.first;
}
}
update();
}
// 수정 후
void changeIncomeType(IncomeType type) {
// 타입이 변경될 때만 처리
if (incomeType.value != type) {
incomeType.value = type;
// 타입에 따라 카테고리 값 명확하게 설정
if (type == IncomeType.income) {
// 수입 타입으로 변경 시
// 지출 카테고리 값 초기화
selectedCategoryE1.value = '';
// 수입 카테고리가 비어있으면 기본값 설정
if (selectedCategory1.value.isEmpty && incomeCategories.isNotEmpty) {
selectedCategory1.value = incomeCategories.first;
}
} else {
// 지출 타입으로 변경 시
// 수입 카테고리 값 초기화
selectedCategory1.value = '';
// 지출 카테고리가 비어있으면 기본값 설정
if (selectedCategoryE1.value.isEmpty && expenseCategories.isNotEmpty) {
selectedCategoryE1.value = expenseCategories.first;
}
}
// 디버깅용 로그
print('컨트롤러에서 타입 변경: $type');
print('수입 카테고리: $selectedCategory1');
print('지출 카테고리: $selectedCategoryE1');
update();
}
}
현재 타입에 맞게 데이터가 저장 되게 함
onTap: () {
if (controller.incomeType.value != item['type']) {
// 먼저 타입 변경
controller.changeIncomeType(item['type']);
// 타입에 따라 카테고리 값 명확하게 설정
if (item['type'] == IncomeType.income) {
// 수입 카테고리 설정
final String? savedCategory = storage.read<String>(incomeCategoryKey);
if (savedCategory != null &&
savedCategory.isNotEmpty &&
controller.incomeCategories.contains(savedCategory)) {
controller.selectedCategory1.value = savedCategory;
// 지출 카테고리 초기화
controller.selectedCategoryE1.value = '';
} else if (controller.incomeCategories.isNotEmpty) {
controller.selectedCategory1.value = controller.incomeCategories.first;
// 지출 카테고리 초기화
controller.selectedCategoryE1.value = '';
}
} else {
// 지출 카테고리 설정
final String? savedCategory = storage.read<String>(expenseCategoryKey);
if (savedCategory != null &&
savedCategory.isNotEmpty &&
controller.expenseCategories.contains(savedCategory)) {
controller.selectedCategoryE1.value = savedCategory;
// 수입 카테고리 초기화
controller.selectedCategory1.value = '';
} else if (controller.expenseCategories.isNotEmpty) {
controller.selectedCategoryE1.value = controller.expenseCategories.first;
// 수입 카테고리 초기화
controller.selectedCategory1.value = '';
}
}
// 디버깅용 로그 추가
print('타입 변경: ${item['type']}');
print('수입 카테고리: ${controller.selectedCategory1.value}');
print('지출 카테고리: ${controller.selectedCategoryE1.value}');
}
}
핵심 수정 사항
- 타입 변경 시 반대 타입의 카테고리 값 초기화: 수입 타입으로 변경 시 지출 카테고리 값을 초기화하고, 지출 타입으로 변경 시 수입 카테고리 값을 초기화합니다.
2. 저장된 카테고리 값 확인: 저장된 카테고리 값이 현재 사용 가능한 카테고리 목록에 있는지 확인합니다.
- 디버깅 로그 추가: 타입 변경 시 카테고리 값이 어떻게 변하는지 확인할 수 있도록 디버깅 로그를 추가했습니다.
결과
이러한 수정을 통해 매출에서 현금을 선택한 후 지출로 전환하여 광고비를 선택했을 때, 광고비가 올바르게 표시되는 문제를 해결했습니다. 또한 반대로 지출에서 광고비를 선택한 후 매출로 전환하여 현금을 선택했을 때도 현금이 올바르게 표시됩니다.
교훈
- 상태 관리의 중요성: 여러 상태가 연결된 애플리케이션에서는 상태 변경 시 관련된 모든 상태를 명확하게 초기화하거나 업데이트해야 합니다.
2. 디버깅 로그의 유용성: 복잡한 상태 관리 문제를 해결할 때 디버깅 로그를 추가하면 문제를 더 쉽게 파악할 수 있습니다.3. 일관된 로직 적용: 동일한 기능이 여러 곳에서 사용될 때는 일관된 로직을 적용하여 예측 가능한 동작을 보장해야 합니다.
'Flutter-플러터 > 플러터 공부' 카테고리의 다른 글
flutter 3.27 버전 local notification 앱 종료 오류 (1) | 2025.02.15 |
---|---|
코딩 독학 2년 개발자가 적어보는 앱 개발하기 전에 꼭 고민해야 할 것 (6) | 2024.11.17 |
코드 리팩토링 중 (1) (2) | 2024.10.06 |
Fltutter - flutter local notification not working in release (0) | 2024.08.08 |
Flutter Google login 개삽질 오류 (0) | 2024.05.17 |