I have several controllers in my code (eg. TextEditingControllers, StreamControllers, ScrollControllers). Is there a way to get a warning/error if I ever forget to call the dispose() method on this variables?
I was hoping that there could be a lint for pedantic, but I couldn't find anything.
To clarify:
If initialize a controller
TextEditingController searchFieldController = TextEditingController();
And then forget to call
#override
void dispose() {
searchFieldController.dispose(); // This line
super.dispose();
}
It should generate a warning
Related
I see people usually initialize the controller like this, initializing it in initState() method.
late VideoPlayerController _videoPlayerController;
#override
void initState() {
super.initState();
_videoPlayerController = VideoPlayerController.network(
"https://assets.mixkit.co/videos/preview/mixkit-spinning-around-the-earth-29351-large.mp4");
}
but then I realize if I just put the controller like this without initState()just put the controller after the variables with late in before the variables, everything works fine. So what is the difference?
class _VideoDetailScreenState extends State<VideoDetailScreen> {
late VideoPlayerController _videoPlayerController = VideoPlayerController.network(
"https://assets.mixkit.co/videos/preview/mixkit-spinning-around-the-earth-29351-large.mp4");
As from the official documentation:
The framework calls initState. Subclasses of State should override initState to perform one-time initialization that depends on the BuildContext or the widget, which are available as the context and widget properties, respectively, when the initState method is called.
i'm building a simple app that prints the result of the current TextFormField. Such as when the text changes it prints the new value.
I found out that you can achieve this with TextEditingController.addListener that listens for changes and executes a function.
So i wrapped it all in initState as follows
#override
void initState() {
addressController.addListener(() {
print(addressController.text);
});
The problem I have is that sometimes it records changes even when there aren't any:
This is what happens writing a word and then deleting it.
If you add listener then you should remove it somewhere, otherwise there can be situation when TextEditingController will have 2 or more listeners:
#override
void initState() {
addressController.addListener(_addressControllerListener);
super.initState()
}
void _addressControllerListener() {
print(addressController.text);
}
#override
void dispose() {
addressController.removeListener(_addressControllerListener);
super.dispose()
}
If i initialise a watcher in the initState() e.g.
textController.addListener(textTypedListener);
Do i need to manually remove the listener before I dispose of the text controller? or does the dispose automatically handle this.
eg. Options 1
#override
void dispose() {
textController.removeListener(textTypedListener);
textController.dispose();
super.dispose();
}
Option 2
#override
void dispose() {
textController.dispose();
super.dispose();
}
Which is best?
Thanks a lot.
According to the Interactive Example given in the flutter documentation of Handle changes to a text field, it's commented that calling dispose also removes the listener.
So the second option would be best.
Should the code that is being written to initState() function be written before super.initState(); or after?
Which one is proper:
#override
// code here
super.initState();
}
or
#override
super.initState();
// code here
}
both will work.
But if you see from any dependencies or official docs flutter, write your code in initSate() after super.initState();
#overrride
initState(){
super.initState()
//your code
}
reference to this initState
the opposite for dispose(), write your code before super.dispose();
#overrride
dispose(){
//your code
super.dispose()
}
reference to dispose
When I see #Kahoo answer, I check it by cmd + click at super.dispose and super.initstate, I found this for dispose
/// If you override this, make sure to end your method with a call to
/// super.dispose().
///
/// See also:
///
/// * [deactivate], which is called prior to [dispose].
#protected
#mustCallSuper
void dispose() {
assert(_debugLifecycleState == _StateLifecycle.ready);
assert(() {
_debugLifecycleState = _StateLifecycle.defunct;
return true;
}());
}
abstract class State :
/// If you override this, make sure your method starts with a call to
/// super.initState().
#protected
#mustCallSuper
void initState() {
assert(_debugLifecycleState == _StateLifecycle.created);
}
Both will work fine, but the better practise is to write before super.initState(), because it will do all the initialisations before creating the state widget which will help you in maintaining the check on the Widget State.
But this does not means that the second method will not keep close eye on maintaining the state, But as of better practise the First way is preferred.
what is the difference between running a method before super.initState() and after super.initState()
#override
void initState() {
super.initState();
getCurrentUser();
}
#override
void initState() {
getCurrentUser();
super.initState();
}
Explanation for framework: Dart is class based object oriented programming language, so when you build a widget you extend it from a base class StatelessWidget or StatefulWidget. initState is lifecycle method in flutter widget (as you might know) which is only available to override in StatefulWidgets and it called only once. So, it call initState of base class which is StatefulWidget thats why you call super.initState()which in turn creates BuildContext and attached State.
Now your question: I didn't find anything different in calling a method before or after super.initState(). Event I tried adding addPostFrameCallback before super.initState() and it worked fine.
Even super.mounted is also true in both cases.
Suggestion
Dart/Flutter documentation "suggests" to call super.initState() as first method before your body implementation.
But if we look at how it is implemented Documentation
#protected
#mustCallSuper
void initState() {
assert(_debugLifecycleState == _StateLifecycle.created);
}
it's possible to see that it contains only an assert(). the assert built-in function it's called only in DEBUG mode, not in production mode. So, at the end of the day, it really doesn't matter, because the super.initState() would practically do nothing.