(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];
}
- 由于参数 'user' 的类型,参数 'user' 的值不能为 'null',但隐式默认值为 'null'。
尝试添加显式非 'null' 默认值或 'required' 修饰符。
(this.user)
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();
}
}
必须初始化不可为 null 的实例字段“_userSubscription”。
尝试添加初始化表达式,或在此构造函数中添加字段初始化器,或将其标记为 'late'.
无法将 'StreamSubscription<User?>' 类型的值赋给 'StreamSubscription' 类型的变量。
尝试更改变量的类型,或将右侧类型转换为 'StreamSubscription'.
无法将参数类型 'User?' 分配给参数类型 'User'。
(_authRepository.user.listen((user) => 添加(AuthUserChanged(user: user)));)
接收者不能为 null,所以 null 感知运算符 '?.'是不必要的。
尝试替换运算符“?”。和 '。'。 (_userSubscription?.cancel();)
操作数不能为空,所以条件总是为真。
删除条件。 (event.user != null)
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,只需在类型末尾添加一个 ?
。有两种不同的方法可以解决这个问题:
- 如果您知道
user
永远不会为空,那么只需执行以下操作:
const AuthState({
required this.user,
this.status = AuthStatus.unknown,
});
required
告诉编译器“嘿,这个变量永远不能设置为 null”。
- 如果
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 文档,以更好地了解所有新运算符和关键字的工作原理。
你好,我正在尝试将旧代码升级到空安全,但由于我刚刚开始学习空安全,我遇到了错误,我无法弄清楚为什么, 如果你能帮上忙我会很高兴
我已经尝试了一些东西,但我保留它的原始形式以免进一步混淆你的东西。源代码: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];
}
- 由于参数 'user' 的类型,参数 'user' 的值不能为 'null',但隐式默认值为 'null'。 尝试添加显式非 'null' 默认值或 'required' 修饰符。 (this.user)
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();
}
}
必须初始化不可为 null 的实例字段“_userSubscription”。 尝试添加初始化表达式,或在此构造函数中添加字段初始化器,或将其标记为 'late'.
无法将 'StreamSubscription<User?>' 类型的值赋给 'StreamSubscription' 类型的变量。 尝试更改变量的类型,或将右侧类型转换为 'StreamSubscription'.
无法将参数类型 'User?' 分配给参数类型 'User'。 (_authRepository.user.listen((user) => 添加(AuthUserChanged(user: user)));)
接收者不能为 null,所以 null 感知运算符 '?.'是不必要的。 尝试替换运算符“?”。和 '。'。 (_userSubscription?.cancel();)
操作数不能为空,所以条件总是为真。 删除条件。 (event.user != null)
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,只需在类型末尾添加一个 ?
。有两种不同的方法可以解决这个问题:
- 如果您知道
user
永远不会为空,那么只需执行以下操作:
const AuthState({
required this.user,
this.status = AuthStatus.unknown,
});
required
告诉编译器“嘿,这个变量永远不能设置为 null”。
- 如果
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 文档,以更好地了解所有新运算符和关键字的工作原理。