(Flutter) 升级到 NullSafety

(Flutter) Upgrading To NullSafety

你好,我正在尝试将旧代码升级到空安全,但由于我刚刚开始学习空安全,我遇到了错误,我无法弄清楚为什么, 如果你能帮上忙我会很高兴

我已经尝试了一些东西,但我保留它的原始形式以免进一步混淆你的东西。源代码:https://github.com/MarcusNg/flutter_instagram


auth_event

    part of 'auth_bloc.dart';

abstract class AuthEvent extends Equatable {
  const AuthEvent();

  @override
  bool get stringify => true;

  @override
  List<Object> get props => [];
}

class AuthUserChanged extends AuthEvent {
  final auth.User user;

  const AuthUserChanged({required this.user});

  @override
  List<Object> get props => [user];
}

class AuthLogoutRequested extends AuthEvent {}

auth_state

part of 'auth_bloc.dart';

enum AuthStatus { unknown, authenticated, unauthenticated }

class AuthState extends Equatable {
  final auth.User user;
  final AuthStatus status;

  const AuthState({
    this.user,
    this.status = AuthStatus.unknown,
  });

  factory AuthState.unknown() => const AuthState();

  factory AuthState.authenticated({required auth.User user}) {
    return AuthState(user: user, status: AuthStatus.authenticated);
  }

  factory AuthState.unauthenticated() =>
      const AuthState(status: AuthStatus.unauthenticated);

  @override
  bool get stringify => true;

  @override
  List<Object> get props => [user, status];
}

auth_bloc

part 'auth_event.dart';
part 'auth_state.dart';


class AuthBloc extends Bloc<AuthEvent, AuthState> {
  final AuthRepository _authRepository;
  StreamSubscription<auth.User> _userSubscription;

  AuthBloc({
    required AuthRepository authRepository,
  })  : _authRepository = authRepository,
        super(AuthState.unknown()) {
    _userSubscription =
        _authRepository.user.listen((user) => add(AuthUserChanged(user: user)));
  }

  @override
  Future<void> close() {
    _userSubscription?.cancel();
    return super.close();
  }

  @override
  Stream<AuthState> mapEventToState(AuthEvent event) async* {
    if (event is AuthUserChanged) {
      yield* _mapAuthUserChangedToState(event);
    } else if (event is AuthLogoutRequested) {
      await _authRepository.logOut();
    }
  }

  Stream<AuthState> _mapAuthUserChangedToState(AuthUserChanged event) async* {
    yield event.user != null
        ? AuthState.authenticated(user: event.user)
        : AuthState.unauthenticated();
  }
}

The parameter 'user' 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. (this.user)

发生此错误是因为您已将 user 变量设置为不可空且 final。如果您不熟悉 nullsafety,要使变量可为 null,只需在类型末尾添加一个 ?。有两种不同的方法可以解决这个问题:

  1. 如果您知道 user 永远不会为空,那么只需执行以下操作:
const AuthState({
    required this.user,
    this.status = AuthStatus.unknown,
  });

required 告诉编译器“嘿,这个变量永远不能设置为 null”。

  1. 如果 user 可以为 null,则执行 final auth.User? user;? 告诉编译器“嘿,这个变量可能为空。

但是在你的情况下你必须选择选项 2 因为这个代码:

factory AuthState.unauthenticated() =>
      const AuthState(status: AuthStatus.unauthenticated);

因为你没有在构造函数中传递 user 你必须告诉 Dart 该变量可以为 null。

Non-nullable instance field '_userSubscription' must be initialized. Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'.

在此处添加 late 标识符:late StreamSubscription<auth.User> _userSubscription;。这告诉 Dart 是的,变量永远不会为空,我只是在定义它时没有设置它。我会将其设置为非空值 ,然后 它会在别处使用。

A value of type 'StreamSubscription<User?>' can't be assigned to a variable of type 'StreamSubscription'. Try changing the type of the variable, or casting the right-hand type to 'StreamSubscription'.

由于 nullsafety,Dart 现在有更严格的类型检查,所以对于这一行,我认为你需要将这一行:StreamSubscription<auth.User> _userSubscription; 更改为 StreamSubscription<auth.User?> _userSubscription;(不要忘记添加 late 就像我之前提到的那样)。

The argument type 'User?' can't be assigned to the parameter type 'User'. (_authRepository.user.listen((user) => add(AuthUserChanged(user: user)));)

AuthUserChanged 中,您取得了 auth.User user required。在该行代码中,您将一个可为空的变量分配给一个不可为空的变量。因此,您必须将 class 更改为如下所示:

class AuthUserChanged extends AuthEvent {
  final auth.User? user;

  const AuthUserChanged({this.user});

  @override
  List<Object> get props => [user];
}

The receiver can't be null, so the null-aware operator '?.' is unnecessary. Try replacing the operator '?.' with '.'. (_userSubscription?.cancel();)

这只是一个警告,你所要做的就是将_userSubscription?.cancel();变成_userSubscription.cancel();。该警告只是让您知道 _userSubscription 永远不会为空,因此您无需使用 ? 运算符检查它是否为空。

The operand can't be null, so the condition is always true. Remove the condition. (event.user != null)

与之前的情况相同。只是一个警告,你所要做的就是删除那行代码,因为它是不必要的。

希望对您有所帮助!我建议查看 Dart 的 nullsafety 文档,以更好地了解所有新运算符和关键字的工作原理。