首页 > 解决方案 > (Flutter) 升级到 NullSafety

问题描述

嗨,我正在尝试将旧代码升级为 null 安全性,但由于我刚刚开始学习 null 安全性,所以我遇到了错误,我不知道为什么,如果你能提供帮助,我会很高兴。

我已经尝试了一些东西,但我将其保留为原始形式,以免让您进一步混淆。源代码: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();
  }
}

标签: flutterdart-null-safety

解决方案


参数 'user' 的值不能为 'null',因为它的类型,但隐含的默认值是 'null'。尝试添加显式的非“null”默认值或“required”修饰符。(这个用户)

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

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

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

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

但是,在您的情况下,由于此代码,您必须使用选项 2:

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

由于你没有传入user构造函数,你必须告诉 Dart 变量可以为空。

必须初始化不可为空的实例字段“_userSubscription”。尝试添加初始化表达式,或在此构造函数中添加字段初始化程序,或将其标记为“迟到”。

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

“StreamSubscription<User?>”类型的值不能分配给“StreamSubscription”类型的变量。尝试更改变量的类型,或将右侧类型转换为“StreamSubscription”。

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

参数类型“用户?” 不能分配给参数类型“用户”。(_authRepository.user.listen((user) => add(AuthUserChanged(user: user)));)

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

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

  const AuthUserChanged({this.user});

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

接收者不能为空,因此可识别空值的运算符 '?.' 是不必要的。尝试替换运算符'?.' 和 '。'。(_userSubscription?.cancel();)

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

操作数不能为空,因此条件始终为真。删除条件。(event.user != null)

与之前的条件相同。只是一个警告,您所要做的就是删除该行代码,因为它是不必要的。

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


推荐阅读