Flutter를 처음으로 null-safety로 고통받는 이야기

13061 단어 DartFlutter

필사적으로 조사한 시간이 낭비된 오치



(추기)
VSCode의 빠른 수정 사용
# VSCode 별로 사용하지 않기 때문에 이런 기능이 있다는 것을 알게 된거야…

다음은 자신이 조사한 내용을 낭비하는 것도 싫었기 때문에 남겨 둡니다.

Flutter를 시작했다



여러가지로 Flutter를 만져 보게 되었다.
스마트 폰 앱 개발은 전혀 미경험이기 때문에 AWS 서비스를 의지하고 여러가지 하려고 생각했다

어울리는 가이드가 있었다.
유석은 AWS

그러나 문제 발생



샘플 코드를 그대로 복사하면 오류가 발생합니다.


오류 1
The parameter 'key' can't have a value of 'null' because of its type, but the implicit default value is 'null'.
Try adding either an explicit non-'null' default value or the 'required' modifier.



오류 2
The property 'authFlowStatus' can't be unconditionally accessed because the receiver can be 'null'.
Try making the access conditional (using '?.') or adding a null check to the target ('!')

원인은 Flutter/Dart 업데이트



여러가지 조사해 보니 null-safety가 원인이라고 알았다
Flutter2의 등장

AWS의 샘플에 한정하지 않고 현시점(2021/06/08)에서 표에 나와 있는 많은 Flutter 해 본 계의 기사의 코드나, 서적의 기재 내용등도 포함해 이 손의 에러가 발생한다.
# 아마 Flutter1.X 시대에 기재된 기사가 많기 때문이라고 생각된다.

그래서 결국 어떻게 하면 에러 해결합니까?



그것을 조사하면 아래에 도착했습니다 Flutter2의 Dart Null Safety를 기존 프로젝트에 도입

오류 수정 방법 2 required 키워드 설정
에러 수정 방법 3 Optional 형으로 랩을 한다

에러 1은 상기 기사의 기재 그대로 해결한다. 어느 쪽이든 괜찮습니다.



login_page.dart
  final VoidCallback shouldShowSignUp;
  LoginPage({required Key key,required this.shouldShowSignUp}) : super(key: key);

login_page.dart
  final VoidCallback? shouldShowSignUp;
  LoginPage({Key? key, this.shouldShowSignUp}) : super(key: key);

Optional 형으로 하면 null 체크의 if문을 작성하지 않으면 null 에러가 발생할 가능성은 있지만, 과거에 접해 온 언어로 null 체크문을 써 온 인간으로부터 하면 이쪽이 다루기 쉬운 것은 아니다 있을까.

오류 2는 위의 방법으로 해결할 수 없습니다.



, 여기서 에러를 토하고 있는 원인은 stream: 옵션으로 지정한 스트림로부터 취득되는 snapshot의 파라미터이다.
# 코드 전체는 원문의 AWS 페이지를 보고 싶다.

main.dart
home: StreamBuilder<AuthState>(
    // 2
    stream: _authService.authStateController.stream,
    builder: (context, snapshot) {
      // 3
      if (snapshot.hasData) {
        return Navigator(
          pages: [
            // 4
            // Show Login Page
            if (snapshot.data.authFlowStatus == AuthFlowStatus.login)
              MaterialPage(child: LoginPage()),

            // 5
            // Show Sign Up Page
            if (snapshot.data.authFlowStatus == AuthFlowStatus.signUp)
              MaterialPage(child: SignUpPage())
          ],
          onPopPage: (route, result) => route.didPop(result),
        );
      } else {
        // 6
        return Container(
          alignment: Alignment.center,
          child: CircularProgressIndicator(),
        );
      }
    }),

StreamController의 stream는 nullable

stream → Stream?
The asynchronous computation to which this builder is currently connected, possibly null. When changed, the current summary is updated using afterDisconnected, if the previous stream was not null, followed by afterConnected, if

그 때문에 거기로부터 취득되는 snapshot도 nullable이라고 생각된다.
# Flutter의 공식 레퍼런스를 읽어도 세세한 기재가 발견되지 않았기 때문에 어디까지나 추정, 유식자의 견해를 할 수 있으면 좋겠다

매개 변수가 nullable이고 if 문에 넣을 수 없다면 변수에 넣어 버리면 좋지 않습니다.

변수에 넣도록 해도 해당 if문이 있는 장소는 pages의 List내이기 때문에 변수 정의는 할 수 없다.
그렇다면 어떻게해야합니까? MaterialPage를 반환하는 함수를 정의하면 된다.

main.dart
  MaterialPage snapshotPage(snapshot){
    AuthFlowStatus status = snapshot.data.authFlowStatus;
    if (status == AuthFlowStatus.login)
      return MaterialPage(
        child: LoginPage()
      );
    if (status  == AuthFlowStatus.signUp)
      return MaterialPage(
        child: SignUpPage()
      );
    // 何も返さない場合は関数がエラーになるため、空ページを返す
    return MaterialPage(child: Scaffold());
  }

...

home: StreamBuilder<AuthState>(
        // 2
        stream: _authService.authStateController.stream,
        builder: (context, snapshot) {
          // 3
          if (snapshot.hasData) {
            return Navigator(
              pages: [
                snapshotPage(snapshot)
              ],
              onPopPage: (route, result) => route.didPop(result),
            );
          }

...

#이라고 생각했지만, 왠지 함수에 인수로서 건네준 후에라면 if문에 그대로 실어도 에러는 되지 않는다
이것은 Dart/Flutter 초학자인 나에게는 원인을 모른다.

main.dart
  MaterialPage snapshotPage(snapshot){
    if (snapshot.data.authFlowStatus == AuthFlowStatus.login)
      return MaterialPage(
        child: LoginPage()
      );
    if (snapshot.data.authFlowStatus == AuthFlowStatus.signUp)
      return MaterialPage(
        child: SignUpPage()
      );
    // 何も返さない場合は関数がエラーになるため、空ページを返す
    return MaterialPage(child: Scaffold());
  }

어쨌든 해결



오류가 해결되어 샘플 앱도 움직이는 것을 확인할 수 있었다.


좋은 웹페이지 즐겨찾기