본문 바로가기
Flutter/Flutter FAQ

Flutter 비동기 간격을 건너서 BuildContext를 사용하지 마십시오., Do not use BuildContexts across async gaps

by 베타코드 2023. 5. 31.
반응형

질문


내 프로젝트에서 새로운 린트 이슈를 발견했습니다.

간단히 말해서:

내 커스텀 클래스에서 BuildContext를 사용해야 합니다.

aysnc 메서드와 함께 사용할 때 flutter 린트 도구가 행복하지 않습니다.

예시:

   MyCustomClass{

      final buildContext context;
      const MyCustomClass({required this.context});

      myAsyncMethod() async {
        await someFuture();
        # if (!mounted) return;          << constructor에 상태를 전달해도 효과가 없음
        Navigator.of(context).pop(); #   << 예시
      }
   }

업데이트: 2022년 9월 17일

BuildContext에 "mounted" 프로퍼티가 곧 추가될 예정입니다.

따라서 다음과 같이 사용할 수 있습니다:

if (context.mounted)

이는 StatelessWidgets도 "mounted"를 확인할 수 있게 합니다.

참고: Remi Rousselet 트윗


답변


Flutter 3.7+ 업데이트 :

mounted 속성이 이제 공식적으로 BuildContext에 추가되어 StatefulWidget State 또는 Stateless widget에서 어디에서든 안전하게 확인할 수 있습니다.

외부 클래스에 context를 저장하는 것은 여전히 좋지 않은 방법이지만, 이제 비동기 호출 후에 안전하게 확인할 수 있습니다. 다음과 같이 :

class MyCustomClass {
  const MyCustomClass();

  Future<void> myAsyncMethod(BuildContext context) async {
    Navigator.of(context).push(/*waiting dialog */);
    await Future.delayed(const Duration(seconds: 2));
    if (context.mounted) Navigator.of(context).pop();
  }
}

// 위젯에서
  @override
  Widget build(BuildContext context) {
    return IconButton(
      onPressed: () => const MyCustomClass().myAsyncMethod(context),
      icon: const Icon(Icons.bug_report),
    );
  }
// 위젯에서

원본 답변

커스텀 클래스에 context를 직접 저장하지 마시고, 비동기 호출 후 위젯이 마운트되었는지 확실하지 않으면 context를 사용하지 마십시오.

다음과 같이 하십시오:

class MyCustomClass {
  const MyCustomClass();

  Future<void> myAsyncMethod(BuildContext context, VoidCallback onSuccess) async {
    await Future.delayed(const Duration(seconds: 2));
    onSuccess.call();
  }
}

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  @override
  Widget build(BuildContext context) {
    return IconButton(
      onPressed: () => const MyCustomClass().myAsyncMethod(context, () {
        if (!mounted) return;
        Navigator.of(context).pop();
      }),
      icon: const Icon(Icons.bug_report),
    );
  }
}
반응형

댓글