`confirmDismiss`와 `onDismissed`

pharmDev·2024년 12월 19일

정리: confirmDismissonDismissed의 차이점과 사용 방법

Flutter의 Dismissible 위젯에서 confirmDismissonDismissed는 삭제 작업을 처리하는 두 가지 주요 방식입니다. 두 방법의 동작 원리, 차이점, 사용 사례, 발생 가능한 문제를 아래에 정리했습니다.


1. onDismissed

동작 원리

  • 사용자가 Dismissible 위젯을 스와이프하면 즉시 삭제 작업을 실행합니다.
  • 삭제 작업 완료 후, Flutter가 해당 항목을 위젯 트리에서 제거합니다.

사용 방법

onDismissed: (DismissDirection direction) async {
  await GetIt.I<AppDatabase>().removeSchedule(schedule.id); // 데이터베이스에서 삭제
  setState(() {
    schedules.remove(schedule); // 데이터 모델에서 삭제
  });
},

특징

  • 삭제 작업이 단순하며, 사용자가 스와이프하면 바로 실행됩니다.
  • 삭제 확인 단계가 없음: 사용자가 실수로 스와이프했을 경우에도 삭제가 바로 실행됩니다.
  • 데이터 모델과 UI가 동기화되지 않으면 위젯 트리에서 제거되지 않았다는 오류가 발생할 수 있습니다.

발생 가능한 문제

  1. 데이터 모델과 UI 동기화 누락:
    • setState를 호출하지 않으면 데이터 모델에서 삭제가 반영되지 않아 UI가 업데이트되지 않을 수 있습니다.
  2. 고유한 key 미설정:
    • Dismissiblekey로 항목을 추적하므로, key가 중복되거나 설정되지 않으면 오류가 발생할 수 있습니다.

2. confirmDismiss

동작 원리

  • 사용자가 항목을 스와이프하면 삭제를 실행하기 전에 삭제 여부를 확인합니다.
  • Future<bool> 값을 반환해야 하며:
    • true 반환 시: 항목이 삭제되고 위젯 트리에서도 제거됩니다.
    • false 반환 시: 항목이 삭제되지 않고 그대로 유지됩니다.

사용 방법

confirmDismiss: (DismissDirection direction) async {
  final confirm = await showDialog<bool>(
    context: context,
    builder: (context) {
      return AlertDialog(
        title: Text('삭제 확인'),
        content: Text('정말로 이 항목을 삭제하시겠습니까?'),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(false), // 삭제 취소
            child: Text('취소'),
          ),
          TextButton(
            onPressed: () => Navigator.of(context).pop(true), // 삭제 승인
            child: Text('삭제'),
          ),
        ],
      );
    },
  );

  if (confirm == true) {
    await GetIt.I<AppDatabase>().removeSchedule(schedule.id); // 데이터베이스에서 삭제
    setState(() {
      schedules.remove(schedule); // 데이터 모델에서 삭제
    });
    return true; // 위젯 트리에서도 삭제
  }

  return false; // 삭제 취소
},

특징

  • 삭제 전에 사용자로부터 확인 단계를 거칠 수 있습니다.
  • 삭제 여부를 조건에 따라 제어할 수 있습니다(예: 특정 조건에서만 삭제 허용).
  • 데이터 모델과 UI가 동기화되지 않으면 동일한 문제가 발생할 수 있습니다.

confirmDismissonDismissed의 차이점

특성onDismissedconfirmDismiss
삭제 확인 단계 제공 여부없음있음 (사용자 확인 또는 조건부 삭제 가능)
항목 제거 방식스와이프 즉시 삭제삭제 여부를 확인한 후 삭제
반환 값없음Future<bool>: true(삭제), false(취소)
위젯 트리 제거 여부 제어데이터 모델에서 직접 제거해야 함true/false 반환으로 자동 제어
사용 목적빠르고 간단한 삭제 작업확인 단계가 필요한 경우 또는 조건부 삭제

오류 발생 이유와 해결 방법

1. 오류 원인

  • 위젯 트리와 데이터 모델 불일치:

    • 데이터 모델에서 항목이 삭제되지 않으면 Flutter는 삭제된 항목을 렌더링하려고 시도하며 오류를 발생시킵니다.
  • 고유한 key 미설정:

    • Dismissible 위젯이 고유한 key를 필요로 합니다. key가 없거나 중복되면 Flutter는 어떤 항목을 삭제해야 할지 추적하지 못합니다.

2. 해결 방법

  1. 데이터 모델에서 삭제 반영:

    • 삭제 작업 이후 setState를 호출하여 데이터 모델과 UI를 동기화해야 합니다.
    setState(() {
      schedules.remove(schedule); // 데이터 모델에서 항목 삭제
    });
  2. 고유한 key 설정:

    • Dismissible에 데이터베이스 ID와 같은 고유한 key를 설정합니다.
    Dismissible(
      key: ObjectKey(schedule.id), // 고유한 ObjectKey 사용
      ...
    );

추천 사용 시나리오

onDismissed를 사용할 때

  • 삭제 작업이 단순하고, 확인 단계가 필요 없는 경우.
  • 사용자가 항목을 스와이프하면 즉시 삭제되어야 할 때.
  • 예: 완료된 작업을 빠르게 삭제하는 간단한 UI.

confirmDismiss를 사용할 때

  • 삭제 전에 확인 단계가 필요한 경우.
  • 조건부로 삭제를 허용해야 하는 경우.
  • 예: 중요한 데이터를 삭제하기 전에 확인 팝업을 띄워야 할 때.

결론

  1. onDismissed는 빠르고 간단한 삭제 작업에 적합하지만, 데이터 모델과 UI를 동기화하지 않으면 오류가 발생할 수 있습니다.
  2. confirmDismiss는 삭제 전에 확인 단계를 추가하거나 조건부 삭제를 처리할 수 있어 더 안전하고 유연합니다.
  3. 데이터 모델과 UI를 항상 동기화하고, 고유한 key를 설정하면 위젯 트리에서 제거되지 않았다는 오류를 방지할 수 있습니다.
profile
코딩을 배우는 초보

0개의 댓글