본문 바로가기
Flutter-플러터/플러터 공부

ReorderList를 사용시에 고려해야 할 것, 가계부앱

by 일기월장 2025. 4. 6.
반응형

 

가계부앱을 만들 때 매출과 지출을 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. 일관된 로직 적용: 동일한 기능이 여러 곳에서 사용될 때는 일관된 로직을 적용하여 예측 가능한 동작을 보장해야 합니다.

 

 

반응형