Why does it keep saying initialize variable? - flutter

Below is the code I wrote. I need to initialize a variable called verificationID for later use. But I keep getting a red squiggly line with the text -
Final variable verificationID must be initialized
Non-nullable instance field vdi must be initialized.
Is this not how you initialize - final [datatype] [name]
I am brand new to flutter and could use any help!
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
enum NumberVerification {
SHOW_MOBILE_FORM_STATE,
SHOW_OTP_FORM_STATE,
}
class LoginScreen extends StatefulWidget {
final String verificationID;
String vdi;
#override
_LoginScreenState createState() => _LoginScreenState();
}

All variables in Dart are getting the value null if nothing else are specified. This is a problem in your case since both verificationID and vdi are specified as non-nullable types (no ? after the type name). So Dart complains about this problem.
Another problem is your final variable which also should be provided a value since this is a read-only variable which can only be assigned a value when initialized.
You therefore need to do:
Change the types to allow null.
Or, provide default value other than null.
Or, make a constructor of your class which gives values to your variables. These values can come from parameters to the constructor.

Because flutter and dart language are null safety. It means you should initialize your variables, and there will be no error regarding this in runtime. So when you write dart codes you must initialize them as follows:
1- In some cases you can init value directly as follows:
final String verificationID = 'value';
2- Or you can get the value from constructor of class.
final String verificationID;
LoginScreen(this.verificationID);
3- And also, you can declare that you will initialize the value later. This way you guarantee that you will initialize the value, so you should use it wisely.
late String verificationID;
verificationID = 'value';
4- Lastly, you may declare a value as nullable. This way, you don't need to initialize the variable directly.
String? verificationID;

Related

Late variable in Dart

I'm new to use Websocket in Flutter.
So I was reading some post (https://blog.logrocket.com/using-websockets-flutter/) to understand how to use websocket, and I have some question.
The guy in this post declare _etheWebsocket,_btcWebsocket variables as late as below.
class CoinbaseProvider {
late final WebSocketChannel _ethWebsocket;
late final WebSocketChannel _btcWebsocket;
CoinbaseProvider()
: _ethWebsocket = WebSocketChannel.connect(
Uri.parse('wss://ws-feed.pro.coinbase.com'),
),
_btcWebsocket = WebSocketChannel.connect(
Uri.parse('wss://ws-feed.pro.coinbase.com'),
);
But why not just declare without late like below??
What is the reason have to declare WebsocketChannel as late.
class CoinbaseProvider {
final WebSocketChannel _ethWebsocket = WebSocketChannel.connect(
Uri.parse('wss://ws-feed.pro.coinbase.com'),
);
final WebSocketChannel _btcWebsocket = WebSocketChannel.connect(
Uri.parse('wss://ws-feed.pro.coinbase.com'),
);
CoinbaseProvider();
Short explanation
You declaration looks better, since in your context you have the values to the variables _ethWebsocket and _btcWebsocket
But why? a dive into late and null-safety features
What's null-safety in Dart? This is a recent released feature (2021) that in summary it prevent us, developers, to create variables of a type that can be implicity null, then avoiding runtime errors as TypeError: can't read property '...' of null
But in summary, unlike before null-safety, now:
All variables can't be null implicity by default!
Show me the code
Before null-safety:
This snippet below is a valid statement before null-safety, this variable can be a String 'hi!' or null
String myVariable; // null by default
After null-safety:
The same snippet now is a invalid statement, the variable should be initialized because her can't be null
String myVariable; // Error!
To declare a variable that can be null by default, as like before the null-safety update you should write as:
String? myVariable; // Note the '?' after the Type
But what if you want to declare variable without the value and without explicitly declaring that it can be null?
The answer is late!
late is just a Dart language feature to allow you say to the compiler: "Hey, I don't have the value of this variable right now, but I promise you I'll set her somewhere else before using it, so her can't be null"
late String myVariable;
print(myVariable); // Throws an LateInitializationError instead of printing 'null'
Conclusion
Given these features and the null-safety use them to avoid wasting time with null pointer exceptions and improve your code typing.
So there's no right or better way, all depends on the context.
For the exact example you used I would say they are identical, and your version would be better. My guess it that they made it like that, is to allow adding additional constructors, maybe like
CoinbaseProvider.customUrl(String eth, String btc)
: _ethWebsocket = WebSocketChannel.connect(
Uri.parse(eth),
),
_btcWebsocket = WebSocketChannel.connect(
Uri.parse(btc),
);

What is the difference between using `late` keyword before the variable type or using `?` mark after the variable type it in the Flutter?

I think in new Dart rules the variables can not be declared/initialized as null. So we must put a late keyword before the variable type like below:
late String id;
Or a ? mark after the variable type like below:
String? id;
Are these two equal Or there are some differences?
A nullable variable does not need to be initialized before it can be used.
It is initialized as null by default:
void main() {
String? word;
print(word); // prints null
}
The keyword late can be used to mark variables that will be initialized later, i.e. not when they are declared but when they are accessed. This also means that we can have non-nullable instance fields that are initialized later:
class ExampleState extends State {
late final String word; // non-nullable
#override
void initState() {
super.initState();
// print(word) here would throw a runtime error
word = 'Hello';
}
}
Accessing a word before it is initialized will throw a runtime error.
when you use late keyword you can't let variable uninitialized when you called it with ? allows to you let variable uninitialized when you create it and call it
Null safety rules doesn't mean you can't use null. You can, but you should indicate that a variable might have the value null, by add "?" to its type declaration.
By use keyword late you indicate that variable has a non-nullable type, is not initialized yet, but will be initialized later.
Exception is thrown if try to acсess value of late variable before initialization.

Flutter i18n shortcut

I'm trying to make a function that get my i18n string by passing variable.
String getStringLanguage(context, String key) {
dynamic translation = AppLocalizations.of(context);
String tmp = key.toString();
return translation.key;
}
but I have this error
Class 'AppLocalizationsFr' has no instance getter 'key'.
Receiver: Instance of 'AppLocalizationsFr'
Tried calling: key
I understand why I have this error, but is it possible to force flutter to use my key variable, instead of searching the key constant ?
this is a small part of my AppLocalizations class
abstract class AppLocalizations {
String get email;
}
Try...
1- Import the library
import 'package:intl/intl.dart';
2- Use the function to get the value
Intl.message(translation.key)

The type 'StateNotifierProvider' is declared with 2 type parameters, but 1 type arguments were given

In the context of a Flutter 2.0.5 app whose state I'd like to manage with Riverpod, I thought I can declare a StateNotifierProvider like this:
import 'package:flutter_riverpod/flutter_riverpod.dart';
final counterProvider = StateNotifierProvider<CounterStateNotifier>((ref) => CounterStateNotifier());
class CounterStateNotifier extends StateNotifier<int> {
CounterStateNotifier([int count = 0]) : super(count);
void increment() => state++;
}
But Android Studio (and later the Dart compiler as well) complains about the line where I declare the counterProvider variable:
The type 'StateNotifierProvider' is declared with 2 type parameters, but 1 type arguments were given.
Removing the <CounterStateNotifier> type parameter in StateNotifierProvider<CounterStateNotifier> removes the error. However, attempting to read the provider and call its increment method (setting () => context.read(counterProvider).increment() as the onPressed of an ElevatedButton, then pressing the button) gives the following runtime error:
'increment'
method not found
Receiver: 0
Arguments: []
Why is context.read(counterProvider) returning the int state instead of the notifier? And what is the reason behind the type parameter error mentioned in the first part of my question?
I should mention that I'm running my app on the web (with flutter run -d Chrome).
As of Riverpod 0.14.0, State is the default value exposed by StateNotifierProvider.
The syntax for declaring your StateNotifierProvider is now as follows:
final counterProvider = StateNotifierProvider<CounterStateNotifier, int>((ref) => CounterStateNotifier());
Accessing functions now requires adding .notifier (accessing the StateNotifier itself):
context.read(counterProvider.notifier).increment();
And like you've noticed, you now access the state like so:
final count = context.read(counterProvider);
More on the changes here.
You may also use dynamic to accept any type if value for the StateNotifierProvider
final modelProvider =
StateNotifierProvider.autoDispose<ModelClassName, dynamic>(
(ref) => ModelClassName());

Dart / flutter test setup with null safety

Update: It was a documentation bug, fixed with: https://github.com/dart-lang/test/pull/1471
According to the docs/examples for the test package (https://pub.dev/packages/test) this test case should work and not trigger warnings. However it does:
The non-nullable local variable 'b' must be assigned before it can be used.
Try giving it an initializer expression, or ensure that it's assigned on every execution path.dart(not_assigned_potentially_non_nullable_local_variable)
Marking the variable as late works, but I want to check that I'm not missing something before I file a bug saying that the docs are wrong. =)
import 'package:test/test.dart';
void main() {
String b;
setUp(() {
b = 'test';
});
group('foo', () {
test('bar', () {
print(b);
});
});
}
You can use late keyword.
ref: https://dart.dev/guides/language/language-tour#late-variables
With Null Safety you have to specifically declare the the variable can be null or you have to initialize it. In this case you may have seen they have also initialized the strings before test. Or You can declare the variable nullable by using
String? b;