Confused About null safety - flutter

I have created a class, and I am getting this error
the operand can’t be null, so the condition is always false.
I am new to flutter and null safety. How can I fix this
class DatabaseHelper{
static late DatabaseHelper _databaseHelper;
factory DatabaseHelper{
if(_databaseHelper==null){
_databaseHelper=DatabaseHelper.internal();
return _databaseHelper;
}else{
return _databaseHelper;
}
}
DatabaseHelper.internal();
}

You've declared using late static late DatabaseHelper _databaseHelper;
Means it will never get null value before read time. And it's just a warning can be ignored.
But if you wish to check value is null or not, or can be null at time, make nullable
like static DatabaseHelper? _databaseHelper;
And when you return it you need to use bang operator ! in some cases,
like return _databaseHelper!;
More details
null-safety faq
null-safety

Related

Operator can't be unconditionally invoked because the receiver can be null

I'm trying to add shopping functions to my app. I'm attempting to use ChangeNotifier to add a cart item counter and I am getting the error message 'error: The operator '-' can't be unconditionally invoked because the receiver can be 'null'. I'm new to coding so I have been unable to figure out a solution even after researching on SO. Thanks in advance for any help provided.
class EcommerceApp {
static late SharedPreferences sharedPreferences;
static String collectionUser = "users";
static String collectionOrders = "orders";
static String userCartList = 'userCart';
static String subCollectionAddress = 'userAddress';
class CartItemCounter extends ChangeNotifier {
final int _counter = EcommerceApp.sharedPreferences
.getStringList(EcommerceApp.userCartList)
?.length - 1;
int get count => _counter;
}
}
The return value of getStringList() has a chance of being null. Dart's Null-safety doesn't allow this. You can use the ?? operator to ensure another value in case of it being null. I think this might work:
class CartItemCounter extends ChangeNotifier {
final int _counter = (EcommerceApp.sharedPreferences
.getStringList(EcommerceApp.userCartList)
.length ?? 0) - 1;
int get count => _counter;
}

what is wrong here? (_instance' has not been initialized)

How I can initialize _instance?
I get "Field '_instance' has not been initialized"
Or any other ways to get rid of nullSafety,,,
here is the code:
class ShoppingBasketData{
static late ShoppingBasketData _instance ;
late List<product> _basketItem;
ShoppingBasketData(){
_basketItem =<product>[];
}
List<product> get basketItem => _basketItem;
set basketItem(List<product> value) {
_basketItem = value;
}
static ShoppingBasketData getInstance(){
if (_instance == null){
_instance = ShoppingBasketData();
}
return _instance;
}
}
What is wrong is that you declared _instance to be late. What that means is that you as a developer promise to initialize it before you access it. If you break that promise, you get an exception.
It seems that you want null to be a valid value, so what you need to do is make it nullable:
static ShoppingBasketData? _instance
You may also want to look into How do you build a Singleton in Dart? so you don't have to reinvent the wheel, and you may want to look into Flutter state management, because singleton is probably the worst of all options.

Riverpod state class default value

e.g. I have class ProfileModel with bunch of fields
many of them don't have default values unless they're initialising when I get user info from backend
with riverpod I need to write something like
final profileProvider = StateNotifierProvider((ref) => ProfileState());
class ProfileState extends StateNotifier<ProfileModel> {
ProfileState() : super(null);
}
I understand I need to pass something like ProfileState.empty() into super() method instead passing null
but in this case I have to invent default values for every ProfileModels fields
this sounds weird for me, I don't want to break my head to care about empty or default state of EVERY model in project
in my example there are no default values for user name, age etc
this is pure immutable class
what I'm doing wrong or missing?
or I can declare model as nullable extends StateNotifier<ProfileModel?>
but I'm not sure is this a good way
It is fine to use the StateNotifier with a nullable model. If you semantically want to indicate the value can be actually absent, I would say that that having null is alright.
However, what I usually do and what I think is better, is create a state model that contains the model, but also properties that relate to the different states the app could be in.
For example, while fetching the data for the model from an API, you might want to have a loading state to show a spinner in the UI while waiting for the data to be fetched. I wrote an article about the architecture that I apply using Riverpod.
A simple example of the state model would be:
class ProfileState {
final ProfileModel? profileData;
final bool isLoading;
ProfileState({
this.profileData,
this.isLoading = false,
});
factory ProfileState.loading() => ProfileState(isLoading: true);
ProfileState copyWith({
ProfileModel? profileData,
bool? isLoading,
}) {
return ProfileState(
profileData: profileData ?? this.profileData,
isLoading: isLoading ?? this.isLoading,
);
}
#override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ProfileState &&
other.profileData == profileData &&
other.isLoading == isLoading;
}
#override
int get hashCode => profileData.hashCode ^ isLoading.hashCode;
}

Non-nullable instance field '_repository' must be initialized

I'm a beginner in flutter, and trying to follow a tutorial.
I'm stuck in the below error :
I have the below code in chat_service.dart that is used to get an API from Laravel/Mysql :
import 'package:buschat/repository/repository.dart';
class ChatService {
Repository _repository;
ChatService() {
_repository = Repository();
}
getAllChats() async {
return await _repository.httpGet('get-all-chat');
}
}
I'm receiving the following error in ChatService() method:
Non-nullable instance field '_repository' must be initialized.
Try adding an initializer expression, or add a field initializer in this constructor, or mark it 'late'
The tutorial is working fine, and it's one year old.
You should try....
class ChatService {
Repository _repository = Repository();
ChatService() {
getAllChats();
}
getAllChats() async {
return await _repository.httpGet('get-all-chat');
}
}
Because of null-safety, all variables must be initialized unless they are marked as nullable. So you need to either give a value to your variable or use late keyword which means you need give it value later but you can't use it as null:
late Repository _repository;
or
// not recommended use (you need to use dependency injection)
Repository _repository = Repository();
You can also mark you variable nullable so you can use it as null:
Repository? _repository;

(Flutter) Upgrading To NullSafety

Hi, I'm trying to upgrade an old code to null safety, but since I'm just starting to learn null safety, I'm encountering errors and I couldn't figure out why, I would be glad if you could help.
I've tried a few things, but I'm leaving it in its original form so as not to confuse things further for you. source code: 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];
}
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)
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();
}
}
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'.
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'.
The argument type 'User?' can't be assigned to the parameter type 'User'.
(_authRepository.user.listen((user) => add(AuthUserChanged(user: user)));)
The receiver can't be null, so the null-aware operator '?.' is unnecessary.
Try replacing the operator '?.' with '.'. (_userSubscription?.cancel();)
The operand can't be null, so the condition is always true.
Remove the condition. (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)
This error is happening because you have set your user variable as non-nullable and final. If you're new to nullsafety, to make the variable nullable, simply add a ? at the end of the type. There's two different routes to fix this one:
If you know that user is never ever going to be null, then simply do this:
const AuthState({
required this.user,
this.status = AuthStatus.unknown,
});
required tells the compiler "hey, this variable can never be set to null".
If user could be null, then do final auth.User? user;. The ? tells the compiler "hey, this variable can potentially be null`.
However in your case you must go with option 2 because of this code:
factory AuthState.unauthenticated() =>
const AuthState(status: AuthStatus.unauthenticated);
Since you don't pass user in the constructor you have to tell Dart that the variable can be 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'.
Add the late identifier here: late StreamSubscription<auth.User> _userSubscription;. This tells Dart that yes, the variable won't ever be null, I am just not setting it when I define it. I will set it to a non-null value before it gets used elsewhere.
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'.
Dart has stricter type checking now due to nullsafety, so for this one I think you need to change this line: StreamSubscription<auth.User> _userSubscription; into StreamSubscription<auth.User?> _userSubscription; (don't forget to add late like I mentioned earlier).
The argument type 'User?' can't be assigned to the parameter type 'User'. (_authRepository.user.listen((user) => add(AuthUserChanged(user: user)));)
In AuthUserChanged, you made auth.User user required. In that line of code, you are assigning a nullable variable to a non-nullable variable. So you have to change the class to look like this:
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();)
This is just a warning, all you have to do is make _userSubscription?.cancel(); into _userSubscription.cancel();. The warning is just letting you know that _userSubscription will never be null so you don't need to check if it is null using the ? operator.
The operand can't be null, so the condition is always true. Remove the condition. (event.user != null)
Same thing as the previous condition. Just a warning, all you have to do is remove that line of code because it is unnecessary.
Hope this helps you! I'd suggest looking at Dart's documentation for nullsafety to get a better idea of how all the new operators and keywords work.