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

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.

Related

Singleton pattern in Dart to make to make shared object

What does this code do? There is no such function _sharedInstance(), at least I didn't find it. Why the code line LoadingScreen._sharedInstance(); used again to define _shared ? Why to use factory there? I.e. this code seems incomprehensible...
class LoadingScreen {
LoadingScreen._sharedInstance();
static final LoadingScreen _shared = LoadingScreen._sharedInstance();
factory LoadingScreen.instance() => _shared;
...
This is a Singleton pattern.
_sharedInstance() is just a private named constructor for LoadingScreen, after defining it the class no longer has a default constructor. You can name it anything and it will be private as long as it starts with _. Check out Named Constructors.
_shared is used to hold the only instance of LoadingScreen, and it gets it's value from invoking the _sharedInstance() private named constructor.
If you call LoadingScreen.instance() in your code, you will always get the same object that is stored in _shared. Check out Factory Constructors.
This is a way to build Singleton. Thanks to Dart's factory constructors, it's easy to build a singleton:
I suggest it needs a couple of points of explanation. There's the weird syntax LoadingScreen. _sharedInstance() that looks like a method call bu actually it's really a constructor definition. There's the _sharedInstance name. And there's the nifty language design point that Dart lets you start out using an ordinary constructor and then if needed, change it to a factory method without changing all the callers.

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());
}

Why can't non-nullable fields be initialized in a constructor body in Dart?

Often times I have an instance field that needs to be initialized in a constructor. For example, it might be needed to be calculated based on other instance fields, hence I can't initialize it inline (where declared) or with a constructor initializer list.
But it either has to be nullable, or declared late, if I need to initialize it in constructor. The rationale behind late keyword is that programmer states "I'll initialize this before using, trust me", when it can not be determined by the compiler that initialization will take place before first usage. BUT: this "programmer guarantee" seems A) terrible and B) unnecessary in case of constructors, because it can be determined by compiler whether the field was initialized in a constructor (and constructor itself is obviously guaranteed to execute before any other instance methods).
Obvious downside to using late fields in such scenarios is that nothing enforces them compile-time to be actually initialized during construction (or anywhere, for that matter). Plus, every time the late field is read, a runtime check is inserted to make sure it has been assigned a value - I don't need that when I initialize in constructors.
Therefore, it seems that, technically it should be possible to have non-nullable non-late fields that are initialized within a constructor body (and if they are not - compiler can throw an error).
So what is the rationale of requiring constructor-initialized fields to be either nullable, or declared as late? Is there a technical reason why this limitation is imposed, or is it just a design oversight by the Dart team?
Dart executes constructor bodies inside-out, from base class to derived class. This allows virtual dispatch to occur in the constructor body. The fact that virtual dispatch can occur in the constructor body means that the compiler cannot statically determine what code will be executed by the constructor body, and therefore it cannot deduce what the constructor body might ultimately initialize.
That the constructor body can execute arbitrary code (including callbacks) that might initialize members or that might depend on initialized members makes it even more complicated.
Furthermore, allowing members to be not initialized when the constructor body runs would be error-prone and a source for confusion. For example, with:
class SomeClass {
int member;
SomeClass() {
updateMember(0);
}
void updateMember(int value) {
print(value); // Oops.
member = value;
}
}
With Dart's current design, all instance methods (and their overrides) can be guaranteed that members are initialized when the method is called. If members were allowed to be uninitialized when the constructor body is executed, that would not longer be true, and all instance methods then would need to consider if they might be invoked from the constructor (or from a base class constructor), possibly indirectly from other method calls, and whether accessed members might not be initialized yet.
(I'll grant that that previous point isn't terribly strong since it currently can still happen that a member is initialized to an object that the constructor body must mutate, but typically instance methods receiving an empty List, Map, etc. is less of a problem than receiving uninitialized members. The above situation also could happen with late members, but that's the baggage that comes with choosing to use late.)
Null-safety disallows the possibility of accessing uninitialized non-late variables, but your proposal would make that possible.
Also, because there is a distinction between initializing members via an initializer list and via a constructor body, people are encouraged to use initializer lists when possible.
The point that you are ignoring here is that when you want to pass a variable to a constructor you will definitely initialize it, otherwise you wouldn't be able to use that widget because you have to pass the variables needed to its constructor. so this late or nullable keywords can be used for the values that you are trying to pass to a widget and not in the widget itself that you are passing them to, but before it.

Why stateful/stateless widgets extends and doesn't implements?

I have this question for a job interview, and i want to know why the stateful and staless widgets, use extends and why not use implements in Flutter/Dart?
Extends
extends is usually the go-to when you want to make a more specific version of a class.
When you extend a class, you inherit all properties, methods, etc.
If you want to override a method, you prefix the method with #override.
Implements
implements is when you want to make a whole new version of a class but you want to inherit the class type.
When you create a new implementation of a class, you are responsible for supplying everything necessary to make that class function.

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).