I am trying to understand the casting system of Dart, in specific with flutter.
I have a List of my custom type I would like to fill in a TableRow, but I simply fail to use map for it. Can anyone help me to point out what my problem is? At the end I need a list of widgets for the children parameter.
TableRow(
children: myList.map((MyType foo) {
return <Widget>[new Text(foo.name)];
}) as List<Widget>
),
The error I am getting is:
flutter: type 'MappedListIterable<MyType, List<Text>>' is not a subtype of type 'List<Widget>' in type cast
Any help is highly appreciated
Just do this:
TableRow(
children: myList.map((foo) {
return new Text(foo.name);
}).toList(),
),
As Rémi says, you need to return a widget inside the map() function, not a list of widgets. And then convert the iterable to a List with toList() method.
Related
im getting these errors and dont know how to fix them.
../AppData/Local/Pub/Cache/hosted/pub.dartlang.org/flutter_platform_widgets-1.20.0/lib/src/platform_button.dart:269:14: Error: The method 'FlatButton' isn't defined for the class 'PlatformButton'.
- 'PlatformButton' is from 'package:flutter_platform_widgets/src/platform_button.dart' ('../AppData/Local/Pub/Cache/hosted/pub.dartlang.org/flutter_platform_widgets-1.20.0/lib/src/platform_button.dart').
Try correcting the name to the name of an existing method, or defining a method named 'FlatButton'.
return FlatButton(
^^^^^^^^^^
../AppData/Local/Pub/Cache/hosted/pub.dartlang.org/flutter_platform_widgets-1.20.0/lib/src/platform_button.dart:302:12: Error: The method 'RaisedButton' isn't defined for the class 'PlatformButton'.
- 'PlatformButton' is from 'package:flutter_platform_widgets/src/platform_button.dart' ('../AppData/Local/Pub/Cache/hosted/pub.dartlang.org/flutter_platform_widgets-1.20.0/lib/src/platform_button.dart').
Try correcting the name to the name of an existing method, or defining a method named 'RaisedButton'.
return RaisedButton(
^^^^^^^^^^^^
../AppData/Local/Pub/Cache/hosted/pub.dartlang.org/flutter_platform_widgets-1.20.0/lib/src/platform_dialog_action.dart:171:14: Error: The method 'FlatButton' isn't defined for the class 'PlatformDialogAction'.
- 'PlatformDialogAction' is from 'package:flutter_platform_widgets/src/platform_dialog_action.dart' ('../AppData/Local/Pub/Cache/hosted/pub.dartlang.org/flutter_platform_widgets-1.20.0/lib/src/platform_dialog_action.dart').
Try correcting the name to the name of an existing method, or defining a method named 'FlatButton'.
return FlatButton(
^^^^^^^^^^
If you're on the latest version of Flutter, Flatbutton is deprecated, use TextButton instead.
**Old Widget change to New Widget
FlatButton => TextButton
RaisedButton => ElevatedButton
OutlineButton => OutlinedButton**
for more details...
https://docs.flutter.dev/release/breaking-changes/buttons#context
FlatButton is deprecated and totally removed from flutter after flutter 2.1.0
Use TextButton instead of FlatButton as follows:
TextButton(
style: TextButton.styleFrom(
foregroundColor: Colors.white,
padding: const EdgeInsets.all(16.0),
textStyle: const TextStyle(fontSize: 20),
),
onPressed: () {},
child: const Text('Gradient'),
),
Check the last package you added in pubspec.yaml and delete it and see if no error occurs then the error is because the package
You just have to change the velocity_x:old version to new version.
For Eg:
in pubspec.yaml
dependencies:
velocity_x:^1.4.1 change it to ^3.2.1
As seen from Flutter Documentation:
Old Widgets have been removed, Now you have to use the new widget along with the new theme. Here is a quick guide on how to use them.
I'm relatively new to Dart/Flutter,
Just struggling to understand some code/syntax and wondered if someone can help explain.
Im looking at the example of setting up multiple providers and I cant get my head round the code for setting up the update..
providers: [
// In this sample app, CatalogModel never changes, so a simple Provider
// is sufficient.
Provider(create: (context) => CatalogModel()),
// CartModel is implemented as a ChangeNotifier, which calls for the use
// of ChangeNotifierProvider. Moreover, CartModel depends
// on CatalogModel, so a ProxyProvider is needed.
ChangeNotifierProxyProvider<CatalogModel, CartModel>(
create: (context) => CartModel(),
update: (context, catalog, cart) {
cart.catalog = catalog;
return cart;
},
),
],
Specifically...
update: (context, catalog, cart) {
cart.catalog = catalog;
return cart;
}
I thought it was a function that takes in 3 parameters context, catelog, cart
But I dont see anywhere where they are first instantiated
Can anyone explain what is going on here?
Thanks
update: denotes a parameter to the ChangeNotifierProxyProvider<CatalogModel, CartModel> constructor, passing it an anonymous function that takes three parameters. The code in (or near) the ChangeNotifierProxyProvider will be invoking this function as necessary.
I'm using a BLoC to keep state between two nested FullScreenDialogs.
I'm initializing the bloc when I push the first screen, like so
return FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => ProductBlocProvider(child: ProductEntryScreen()),
fullscreenDialog: true
));
},
);
ProductEntryScreen has a bunch of TextFields and a button than opens a new FullScreenDialog. This new Screen also has TextFields.
The problem I'm having is that every time I write on a TextField on the second FullScreenDialog, the onPressed function where I start the ProductBlocProvider runs again.
And that re-run is causing the Bloc to create a new instance, so I end up loosing the state.
What I want to do?
Maybe I'm doing it wrong so I'll explain what I'm trying to achieve.
I want to keep state between the two FullScreenDialogs while I fill all the fields, and when I'm done I want to press a button that send all of the data (both screens) to a database.
The problem is that I was creating the instance of the bloc inside the provider in the builder function of the MaterialPageRoute.
That builder function was being called repeatedly, and creating a new instance of the bloc every time. The solution was to take out from the builde function the creation of the bloc instance, like this:
return FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
//Here I create the instance
var _bloc = ProductBloc();
Navigator.of(context).push(MaterialPageRoute(
//And I pass the bloc instance to the provider
builder: (BuildContext context) => ProductBlocProvider(bloc: _bloc, child: ProductEntryScreen()),
fullscreenDialog: true
));
},
);
The package get_it may be of help to you. get_it is a service locator library, and uses a Map to store the registered objects; therefore, it provides access at a complexity of O(1), which means it's incredibly fast. The package comes with a singleton GetIt which you can use like so,
// Create a global variable (traditionally called sl or locator)
final sl = GetIt.instance; // There is also a shorthand GetIt.i
// ...
// Then, maybe in a global function called initDi(),
// you could register your dependencies.
sl.registerLazySingleton(() => ProductBloc());
registerLazySingleton() or registerSingleton() will always
return the same instance; lazily (i.e., when first called)
or at app start-up respectively.
If you want to create a new instance every time, use registerFactory() instead (I put this here even though it's not exactly what you want).
For example,
sl.registerFactory(() => ValidatorCubit());
And it could be accessed like this,
MultiBlocProvider(
providers: [
// The type is inferred here
BlocProvider<AuthenticationBloc>(create: (_) => sl()),
// The type is explicitly given here
BlocProvider(create: (_) => sl<ProductsBloc>()),
],
child: ProductsScreen(),
),
This example primarily shows you how it can be done with the flutter_bloc library, but get_it works anywhere, even in non-flutter dart projects.
If you need more functionality, do make sure to read the docs for this package. It is well documented, and contains (almost) every feature you might need, including scoping.
Also, this approach allows you to use the interface pattern, making the code much more maintainable and testable, as you will have to change just one place to use a different implementation.
In the flutter docs there's sample code for a stateless widget subclass as shown:
class GreenFrog extends StatelessWidget {
const GreenFrog({ Key key }) : super(key: key);
#override
Widget build(BuildContext context) {
return new Container(color: const Color(0xFF2DBD3A));
}
}
and this
class Frog extends StatelessWidget {
const Frog({
Key key,
this.color: const Color(0xFF2DBD3A),
this.child,
}) : super(key: key);
final Color color;
final Widget child;
#override
Widget build(BuildContext context) {
return new Container(color: color, child: child);
}
}
What is a key and when should this super constructor be used? It seems like if you have your own constructor you must have {Key key} why? I've seen other examples where the super keyword is not used so this is where my confusion is.
TLDR: All widgets should have a Key key as optional parameter or their constructor.
Key is something used by flutter engine at the step of recognizing which widget in a list as changed.
It is useful when you have a list (Column, Row, whatever) of widgets of the same type that can potentially get removed/inserted.
Let's say you have this (code not working, but you get the idea) :
AnimatedList(
children: [
Card(child: Text("foo")),
Card(child: Text("bar")),
Card(child: Text("42")),
]
)
Potentially, you can remove any of these widgets individually with a swipe.
The thing is, our list has an animation when a child is removed. So let's remove "bar".
AnimatedList(
children: [
Card(child: Text("foo")),
Card(child: Text("42")),
]
)
The problem: Without Key, flutter won't be able to know if the second element of your Row disappeared. Or if it's the last one that disappeared and the second has its child change.
So without Key, you could potentially have a bug where your leave animation will be played on the last element instead!
This is where Key takes place.
If we start our example again, using key we'd have this :
AnimatedList(
children: [
Card(key: ObjectKey("foo"), child: Text("foo")),
Card(key: ObjectKey("bar"), child: Text("bar")),
Card(key: ObjectKey("42"), child: Text("42")),
]
)
notice how the key is not the child index but something unique to the element.
From this point, if we remove "bar" again, we'll have
AnimatedList(
children: [
Card(key: ObjectKey("foo"), child: Text("foo")),
Card(key: ObjectKey("42"), child: Text("42")),
]
)
Thanks to key being present, flutter engine now knows for sure which widget got removed. And now our leave animation will correctly play on "bar" instead of "42".
What are Keys?
Keys are IDs for widgets. All widgets have them, not just StatelessWidgets. They are used by the Element tree to determine if a widget can be reused or if it needs to be rebuilt. When no key is specified (the usual case), then the widget type is used to determine this.
Why use Keys?
Keys are useful for maintaining state when the number or position of widgets changes. If there is no key then the Flutter framework can get confused about which widget changed.
When to use Keys?
Only use them when the framework needs your help to know which widget to update.
Most of the time you don't need to use keys. Since keys are mostly only useful for maintaining state, if you have a stateless widget whose children are all stateless, then there is no need to use a key on it. It won't hurt to use a key in this case, but it also won't help.
There are some micro-optimizations you can make using keys. See this article.
Where to use Keys?
Put the key at the part of the widget tree where the reordering or addition/deletion is taking place. For example, if you are reordering the items of a ListView whose children are ListTile widgets, then add the keys to the ListTile widgets.
What kind of Keys to use?
A key is just an id, but the kind of ID you use can vary.
ValueKey
A ValueKey is a local key that takes a simple value like a string or integer.
ObjectKey
If you widget is displaying more complex data than a single value, then you can use an ObjectKey for that widget.
UniqueKey
This type of key is guaranteed to give you a unique ID every time. If you use it, though, do NOT put it in the build method. Otherwise your widget will never have the same ID and so the Element tree will never find a match to reuse.
GlobalKey
GlobalKeys can be used to maintain state across your app, but use them sparingly because they are similar to global variables. It is often preferable to use a state management solution instead.
Examples of using Keys
AnimatedLists
Changing the position in a column/row
TextFormField
References
Keys! What are they good for?
Using Keys in Flutter
Key is object that is used to identify a widget uniquely.
They are used to access or restore state In a StatefulWidget (Mostly we don't need them at all if our widget tree is all Stateless Widgets).
There are various types of key that I will try to explain on the basis of usage.
Purpose (key types)
1. Mutate the collection i.e. remove / add / reorder item to list in stateful widget like draggable todo list where checked items get removed
➡️ ObjectKey, ValueKey & UniqueKey
2. Move widget from one Parent to another preserving it's state.
➡️ GlobalKey
3. Display same Widget in multiple screens and holding its state.
➡️ GlobalKey
4. Validate Form.
➡️ GlobalKey
5. You want to give a key without using any data.
➡️ UniqueKey
6. If you can use a certain fields of data like UUID of users as unique Key.
➡️ ValueKey
7. If you do not have any unique field to use as key but object itself is unique.
➡️ ObjectKey
8. If you have multiple Forms or Multiple Widgets of the same type that need GlobalKey.
➡️ GlobalObjectKey, LabeledGlobalKey whichever is appropriate, similar logic to ValueKey and ObjectKey
❌ Do not use random string/number as key, it defeats the purpose of keys ❌
The Key is an optional parameter needed to preserve state in your widget tree, you have to use them if you want to move a collection of elements in your tree and preserve the state of them.
The best explanation can be found in this video by Google When to Use Keys - Flutter Widgets 101 Ep. 4
With Dart 2.12 or later, add ? after Key to make it optional if you want.
class Frog extends StatelessWidget {
const Frog({
Key? key,
this.color: const Color(0xFF2DBD3A),
this.child,
}) : super(key: key);
final Color color;
final Widget child;
#override
Widget build(BuildContext context) {
return new Container(color: color, child: child);
}
}
Im looking through flutter docs and examples and im stuck in the routing.
Here is documentation https://docs.flutter.io/flutter/widgets/Navigator-class.html
It tells I can do a button with function to navigate with Navigator
onPressed: (context) {
Navigator.pop(context);
}
but my ide (vs code) and debugger doesn't think it is possible. It shows me error when im trying to do it.
[dart] The argument type '(dynamic) → Null' can't be assigned to the parameter type '() → void'.
Build also fails with exceptions
setState() or markNeedsBuild() called during build.
This Overlay widget cannot be marked as needing to build because the framewo…
not quite sure what it means...
Any suggestions?
You don't need to pass context to the onPressed callback, context is available inside the callback anyway if the callback is created in a scope where context is available:
build(BuildContext context) {
...
onPressed: () {
Navigator.pop(context);
}
}
Do not pass the context to onPressed as it is a void callback, so it does not return anything. Use it only to execute logic.