In my application, I use these 2 classes but I don't know which one I should prioritize.
Image.asset('icons/heart.png')
AssetImage('icons/hear.png')
Maybe there is one who fetches the image faster.
Image is a StatefulWidget and Image.asset is just a named constructor, you can use it directly on your widget tree.
AssetImage is an ImageProvider which is responsible for obtaining the image of the specified path.
If you check the source code of the Image.asset you will find that it's using AssetImage to get the image.
Image.asset(String name, {
Key key,
AssetBundle bundle,
this.semanticLabel,
this.excludeFromSemantics = false,
double scale,
this.width,
this.height,
this.color,
this.colorBlendMode,
this.fit,
this.alignment = Alignment.center,
this.repeat = ImageRepeat.noRepeat,
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
String package,
this.filterQuality = FilterQuality.low,
}) : image = scale != null
? ExactAssetImage(name, bundle: bundle, scale: scale, package: package)
: AssetImage(name, bundle: bundle, package: package),
assert(alignment != null),
assert(repeat != null),
assert(matchTextDirection != null),
super(key: key);
Thanks #diegoveloper
From flutter version 2.5, it is recommended to use the Image StatefulWidget with the const modifier which is impossible with Image.asset. However, you'll need to provide the image path as a parameter to the AssetImage object, where this object is the value of the named parameter 'image' of the Image StatefulWidget, like so.
Image(
image: AssetImage('asset/dice1.png'),
)
From the recommended Dart tutorial book Dart Apprentice const and final modifiers on objects reduce subsequent compile-time and runtime.
Therefore for clean and few lines of code, use Image.asset, but for fast and CPU-friendly code, use Image StatefulWidget.
Related
I have a provider named gameControllerProvider extends with ChangeNotifier, I initialize it first throw UnimplementedError.
final gameControllerProvider =
ChangeNotifierProvider<GameController>((ref) => throw UnimplementedError());
In my GameBodyWidget I ovverridewith value my gameControlllerProvider
class GameBodyWidget extends ConsumerWidget {
/// {#macro game_body_screen}
const GameBodyWidget({Key? key, required this.gameLevel}) : super(key: key);
final GameLevel gameLevel;
#override
Widget build(BuildContext context, WidgetRef ref) {
return ProviderScope(
overrides: [
gameControllerProvider.overrideWithValue(
GameController()..initializeController(gameLevel, ref),
),
],
child: Stack(
...
),
);
}
As you can see, the reason why I override the controller provider because I need to initialize and pass the parameter of WidgetRef and the GameLevel instance.
Yeah I know I can use the .family method but the problem there is that when I need to call this provider I always pass the parameter
ref.watch(gameControllerProvider('exampleParameter'));
As the changelog says, overrideWithValue is temporarily removed.
But to begin with, in the code you shared, you shouldn't be using it.
Instead do:
ProviderScope(
overrides: [
gameControllerProvider.overrideWithProvider(
ChangeNotifierProvider((ref) {
return GameController()..initializeController(gameLevel, ref),
}),
),
],
)
Using overrideWithValue here is unsafe as a ChangeNotifier is a stateful object. If the widget somehow rebuilt, your ChangeNotifier would be recreated and your state would be lost.
Using overrideWithProvider does not have this issue, as the provider will cache the ChangeNotifier.
For now you can use overrideWithProvider.
This change is temporary, and these methods will be reintroduced in a later version.
I am trying to make a social networking site using flutter . This is a feed related page which stores if there are feed available for the user or not and if there are feed it shows it . I am using asynchronous method for action during feed update so while creating on-pressed it is showing an error while creating PostCreateRoute object that the argument type '_PostCreateRoute' can't be assigned to the parameter type 'Route'. and I am new to flutter and if someone can help me out it would be great .
class _FeedActionButtonState extends State<FeedActionButton> {
BuildContext _context;
#override
Widget build(BuildContext context) {
_context = context;
return new FloatingActionButton(
child: new Icon(Icons.add, color:Theme.of(context).iconTheme.color),
onPressed: onPressed,
backgroundColor: Colors.white);
}
onPressed() async{
Mappost=await
Navigator.of(_context).push(new_PostCreateRoute(_context));
if (post!=null &&widget.onPosted!=null){
this .widget.onPosted(post)
}
}
}
It looks like you are passing _PostCreateRoute() as an argument to the push function which only accepts the arguments of type Route().
You first need to wrap your class in a route object like MaterialPageRoute (Android) or CupertinoPageRoute (iOS).
You can try something like:
Navigator.push(_context, MaterialPageRoute(builder: (BuildContext _context) => _PostCreateRoute(_context)));
Make sure you import material.dart or cupertino.dart depending on which route type you go with.
Is there an alternative to Navigator.push which doesn't require a context? Here is my problem.
I have a very nested and deep callstack and not each function has a BuildContext parameter. Is there any other way to get the current BuildContext than through passing it from one function to another?
test1.dart
Widget build(BuildContext) {
...
new GestureDetector(
onTap: () => foo1() // very deep callstack until it calls foo30
...
}
test2.dart
void foo30() {
// need context here like:
BuildContext context = IHopeThatExists.getCurrentContext();
// why do I need that? Navigator.push needs a context or is there an alternative? FYI: I don't need to go back to the previous page though
Navigator.push(context, ..)
}
You can use the Builder widget:
return Builder(
builder: (context) {
return RaisedButton(
onPressed: () {
Navigator.of(context).push(...);
},
...
);
},
);
If your call stack is that deep you might want to consider refactoring =D. But that aside, if you use a StatefulWidget it has a context property which is the same as what is passed to the build function.
And FYI - from the State.build docs:
The BuildContext argument is always the same as the context property
of this State object and will remain the same for the lifetime of this
object. The BuildContext argument is provided redundantly here so that
this method matches the signature for a WidgetBuilder.
This question already has answers here:
What is the difference between named and positional parameters in Dart?
(7 answers)
Closed 4 years ago.
I have this constructor in my class. Now when it's like this, I get
The type parameter icon is annotated with #required
but only named parameters without default value can be annotated with it.
-
const Category(
#required this.name,
#required this.icon,
#required this.color
) : assert(name != null),
assert(icon != null),
assert(color != null);
And when calling the constructor like this:
Category(name: _categoryName, icon: _categoryIcon, color: _categoryColor),
It's an error.
All of this goes away when I surround my constructor arguments with {}.
What does this mean?
{} are missing to make them named parameters
const Category({
#required this.name,
#required this.icon,
#required this.color
}) : assert(name != null),
assert(icon != null),
assert(color != null);
or just remove #required
Without {} they are positional parameters which are required anyway.
Category('foo', someIcon, Colors.white)
vs
Category(name: 'foo', icon: someIcon, color: Colors.white)
[] makes them optional positional parameters.
Positional (non-optional) need to be declared first, optional parameters come at the end.
Optional positional and optional named parameters can not be used together.
Optional parameters (positional and named) can have default values
this.name = 'foo'
Default values need to be compile-time constants.
You have used named optional arguemnts but your constructor accept postional optional parameter.
named optional parameter {}:
Use to omit/avoid arguments and for readability.
argument position doesnt matter since refer using name.
Since you can avoid the argument, to denote that this argument is required use #required. Most of the time this annotation use to say this is cannot avoid(like a notice).
const Category({
#required this.name,
#required this.icon,
#required this.color
}) : assert(name != null),
assert(icon != null),
assert(color != null);
//Category(name: _categoryName, icon: _categoryIcon, color: _categoryColor),
positional optional parameter []:
Also use to avoid or omit args.
Cannot mention name because of that no readability(as a example for boolean params).
Argument position matters.
No need of #required because we must provide args.
const Category(
this.name,
this.icon,
this.color
) : assert(name != null),
assert(icon != null),
assert(color != null);
//Category(_categoryName, _categoryIcon, _categoryColor),
Read more from this SO answer.
#required is a hint that some value should be passed as an argument to this parameter, even if it's just the default.
This hint only makes sense when used with optional parameters, such as when you surround the parameters with braces, because otherwise arguments are mandatory anyways (like what you would be used to in e.g. java.
Naming is a bit unfortunate here but named parameters in dart also mean they're optional, you can call a function without any of them.
Background: I'm trying to inherit from AnimatedCrossFade to apply this patch https://github.com/flutter/flutter/issues/10243 as a subclass (rather than forking flutter). I'm just learning dart/flutter, and honestly I thought that creating a cross-fade from a loading widget to a network image would have been a really simple thing to try first (it's not easy at all, FadeInImage doesn't crossfade nor does it take a widget [despite the design goal of nearly everything in flutter being a widget],Image.network does not have a onDownloadCompleted callback, and AnimatedCrossFade has the aforementioned bug with centering). Anyway...
Here's the code I'm calling:
class FixedCrossFade extends AnimatedCrossFade {
const FixedCrossFade({
Key key,
#required firstChild,
#required secondChild,
firstCurve: Curves.linear,
secondCurve: Curves.linear,
sizeCurve: Curves.linear,
alignment: Alignment.topCenter,
#required crossFadeState,
#required duration,
layoutBuilder: AnimatedCrossFade.defaultLayoutBuilder,
}) : super(
key,
firstChild,
secondChild,
firstCurve: firstCurve,
secondCurve: secondCurve,
alignment: alignment,
crossFadeState: crossFadeState,
duration: duration,
layoutBuilder: layoutBuilder
);
}
For reference, this is AnimatedCrossFade's constructor:
const AnimatedCrossFade({
Key key,
#required this.firstChild,
#required this.secondChild,
this.firstCurve: Curves.linear,
this.secondCurve: Curves.linear,
this.sizeCurve: Curves.linear,
this.alignment: Alignment.topCenter,
#required this.crossFadeState,
#required this.duration,
this.layoutBuilder: defaultLayoutBuilder,
}) : assert(firstChild != null),
assert(secondChild != null),
assert(firstCurve != null),
assert(secondCurve != null),
assert(sizeCurve != null),
assert(alignment != null),
assert(crossFadeState != null),
assert(duration != null),
assert(layoutBuilder != null),
super(key: key);
My FixedCrossFade class errors with:
error: line 33 pos 8: invalid arguments passed to super class constructor 'AnimatedCrossFade.': 3 passed, 0 expected
Where line number 33 corresponds to the line }) : super(
I'm not actually changing the constructor, I believe all I need to do is overrride createState, and completely reimplement the state object. Coming from a python / C++ background, I was quite surprised that extending AnimatedCrossFade without any changes causes an error:
class FixedCrossFade extends AnimatedCrossFade {}
...
No constructor 'FixedCrossFade' declared in class 'FixedCrossFade'
I'm very very new to dart and flutter, so this is probably a very simple mistake. Any help is appreciated!
As you noticed, the super-constructor has only named parameters, but you are passing key, firstChild and secondChild without a name, so they are positional arguments. Change those to:
}) : super(
key : key,
firstChild: firstChild,
secondChild: secondChild,
firstCurve: firstCurve,
and the super-invocation will work.
You need to add a constructor because constructors are not inherited. They are not instance methods, they are rather more like static methods which are also not inherited. So, for your class to have any constructor, it needs to declare it, and then call a suitable generative super-constructor to create the superclass. It's, admittedly, annoying when all you do is forward arguments.