Is ScaffoldWidget InheritedWidget? - flutter

I'm confused because the blog I saw introduced ScaffoldWidget as InheritedWidget. In the ScaffoldWidget body, InheritedWidget is not used, but it seems to be treated as InheritedWidget for using the of method.
Is ScaffoldWidget InheritedWidget?
Is the of method like a naming convention?

Related

Flutter What is difference between valueNotifier,changeNotifier,stateNotifier?

What is difference between valueNotifier,changeNotifier,stateNotifier?
ValueNotifier is a special type of class that extends Changenotifier, which can hold a single value and notifies the widgets which are listening to it whenever its holding value gets change.
ChangeNotifier is a class that provides change notification to its listeners. That means you can subscribe to a class that is extended or mixed in with ChangeNotifier and call its notifyListeners() method when there’s a change in that class. This call will notify the widgets that are subscribed to this class to rebuild.
On the other hand, StateNotifier is an immutable state management solution where the state can be directly changed within the notifier only.
There is an interesting difference between ValueNotifier and StateNotifier. The former uses == to assess whether update is needed, while later uses identical check. This has positive performance implications in favor of the later as long as immutable types are used. See https://github.com/rrousselGit/state_notifier#why-are-listeners-called-when-the-new-state-is--to-the-previous-state
For built-in "value types" and enums they work just the same.
One may be tempted to use ValueNotifier for mutable objects, but this doesn't work well because sub-objects of that object can be changed via mutating methods, and this clearly does not trigger updates.
StateNotifier also has some additional options, such as modifying when the value is actually updated.
Therefore my current recommendation is:
Use ChangeNotifier for mutable types.
Use StateNotifier for immutable types.
Ignore ValueNotifier.
StateNotifier is intended to be used with immutable objects, but there is no mechanism in the language to ensure this is the case. This compiles:
class Mutable {
Object? o;
}
class Mistake extends StateNotifier<Mutable> {
Mistake() : super(Mutable());
}

The member 'notifyListeners' can only be used within 'package:flutter/src/foundation/change_notifier.dart' or a test

I am using ChangeNotifier and i change their value and notify like below,
// Declare
ValueNotifier<bool> isDisplay = new ValueNotifier(false);
// Change value
isDisplay.value = false;
isDisplay.notifyListeners();
It's working fine. but it's raise warning like below,
Can we resolve this using proper implementation or other things ?
I was getting these errors too, more specifically, those 2:
The member 'notifyListeners' can only be used within instance members of subclasses of 'package:flutter/src/foundation/change_notifier.dart'.dart(invalid_use_of_protected_member)
The member 'notifyListeners' can only be used within 'package:flutter/src/foundation/change_notifier.dart' or a test.dart(invalid_use_of_visible_for_testing_member)
After a bit of research, I've come to some conclusions and a solution. Thought I should share it with people who encounter this problem.
The problem
What it says actually is quite obvious, “If you wanna call notifyListeners(), you have to do it in a subclass of ChangeNotifier or in a test file”
“But why is that?” Understandably, this was my second question. But before that, a little bit about where the heck that notifyListeners method is coming from
notifyListeners method
If you look at the implementation of ValueNotifier, it extends ChangeNotifier class:
and ChangeNotifier has a notifyListeners() method (which is why, in the first place, we can use this method) but not in a usual way:
It's protected.
#protected annotation in Dart | doc
[#protected annotation] Indicates that the annotated instance member (method, getter, setter, operator, or field) m in a class or mixin C should only be referenced in specific locations.
A reference from within the library in which C is declared is valid. Additionally, a reference from within an instance member in C, or a class that extends, implements, or mixes in C (either directly or indirectly), or a mixin that uses C as a superclass constraint is valid. Additionally, a reference from within an instance member in an extension that applies to C is valid.”
In a more worldly explanation: it can be used in subclasses that directly extends (or mixins) the ChangeNotifier class or in test files. Since you want to use it in your logic code, you have to do the first section in this paragraph: “extend or mixin ChangeNotifier where you want to call notifyListeners method.”
Where to extend (or mixin) the ChangeNotifier class?
You may be tempted to use it in your Stateful or Stateless Widget, and, since Dart is single-inheritance, you'd have to “mixin” the ChangeNotifier class to your class, but you'd be wrong.
1. Why you must not mixin to StatefulWidget
ChangeNotifier class defines its own dispose method. And since the class or mixin that mixins to your class supersedes the previous inherited methods, by looking at the methods of ChangeNotifier, you'll notice the dispose method (which is used to remove the listeners). So, if you mix ChangeNotifier to StatefulWidget, now your dispose would be ChangeNotifier's dispose rather than the State's dispose.
Remember, you have to release the resources used by State class no matter what. Normally, if you do not override the dispose method in your State, the framework does this for you and releases the resources by itself, which is cool; but since you just changed the dispose method's ancestor, framework will not trigger the required dispose method. And that will raise a runtime error.
2. Why you must not mixin to StatelessWidget
And on the StatelessWidget's case, now your widget would have an instance variable _listener that's not final which comes from the mixed ChangeNotifier. So, you couldn't define a const constructor, which is the most important part of a StatelessWidget (talking about widget rebuild and performance-related situations).
What to do?
In the end, a solution to this would be, to create a new class to manipulate value changes and extend or mixin ChangeNotifier to this class. Then you can call notifyListeners() method wherever and whenever you like! (but of course, don't call notifyListeners unless you use complex objects or send the same value)
Also, these classes are preferably called as 'Controller', 'ViewModel', 'BLoC', or any other name to state that they're mutating/controlling your values and trigger UI to rebuild when needed. (Which what you should do in the first place: separate your UI from your Logic layer).
Further readings
State management for minimalists
You do not need to call notifyListeners, as this is automatically called when a new value is set.
ChangeNotifier implementations like ValueListener should never require notifyListeners to be called manually.

Is state the same thing as class variables and their values?

I'm struggling to understand the concept of state in Flutter. I'm coming from languages like Delphi, Python, and C#, and thinking:
everything is a widget in Flutter is the same as everything is an object (class instance) in other languages
a widget is an object inheriting from a class with a build method, analogous to classes with OnPaint or OnShow methods in other languages
object properties (member variables) make up a widget/object's state. If there are no member variables or they are all declared as const or final, then the widget is stateless. If not then the properties and their values make up the widget/object's state.
What am I missing? What makes up state beside variables?
PS I get further confused when I read about Flutter elements and element trees, though I may understand better once I've got a handle on widget state.
object properties (member variables) make up a widget/object's state. If there are no member variables or theys are all declared as const or final, then the widget is stateless. If not then the properties and their values make up the widget/object's state.
This point is incorrect. Widgets are always immutable, but a StatefulWidget contains a reference to a State instance. States are where your mutable data is held. They have a much longer life than a typical widget, and include special state management methods such as initState(), setState(). They also have a build() method like widgets and for the most part seem like a widget, but they are actually a State<Widget>.
Should you use a StatelessWidget or a StatefulWidget? This question comes up a lot when starting Flutter development. My rule of thumb is that unless you know you really need a StatefulWidget, start with a stateless one. The reason being they are simpler and the most popular IDEs can convert a StatelessWidget to a StatefulWidget (and produce the corresponding State-extending class).

Flutter immutable class?

IDE recognised StoreWatcher Flutter Widget as immutable. Where is that #immutable annotation? It is not in the store_watcher.dart source code.
The annotation is from the meta package
The docs say
Used to annotate a class C. Indicates that C and all subtypes of C
must be immutable.
A class is immutable if all of the instance fields of the class,
whether defined directly or inherited, are final.
Tools, such as the analyzer, can provide feedback if
the annotation is associated with anything other than a class, or a
class that has this annotation or extends, implements or mixes in a
class that has this annotation is not immutable.
Not all annotation cause the expected feedback yet.
Some might need to enable linter rules.
For some it might only planned yet to be supported eventually by the analyzer or the linter.

Was the "interface" keyword removed from Dart?

Just to be sure, has Dart removed explicitly defining an interface now in favor of implicitly defining it via abstract?
I see it mentioned in Dart and Interface Segregation Principle, however I'm also finding a lot of content still referencing the explicit definition, such as When to use interfaces in Dart?
Yes. The interface keyword was removed from Dart. Instead all classes have implicit interfaces. So if you want to define an interface you can use an abstract class instead.
See this blog post from 2012 about eliminating the interface keyword.