How to Add and Use key in Custom widget constructors - flutter

I got notification warning (Not Error) about Use key in widget constructors. let say I have stateless class like this :
class TeaTile extends StatelessWidget {
final TheTea? tea;
const TeaTile({this.tea}); //the warning in hire!
#override
Widget build(BuildContext context) {
return Container();
}
}
the basic stateless format has a key like this :
class TeaTile extends StatelessWidget {
const TeaTile({ Key? key }) : super(key: key); //this one
#override
Widget build(BuildContext context) {
return Container();
}
}
I know how to disable the key rule use_key_in_widget_constructors: false. but I don't want to do it. so, how I add key in
final TheTea? tea;
const TeaTile({this.tea});
to solve the warning notification?

Update for Dart 2.17 using Super Initializers:
final TheTea? tea;
const TeaTile({ super.key, this.tea });
The super keyword in a constructor is a shortcut for the method below.
Older Dart versions:
final TheTea? tea;
const TeaTile({ Key? key, this.tea }) : super(key: key);
Basically a combination of both, you're still taking a named parameter key, that will pass it's value to the super constructor, and another named parameter tea that would set your final variable value.

Related

How to set default value of function in a constructor (Flutter)

I want to set default function in my child Widget in a constructor.
Basically, I have two widgets
Login (Parent Widget)
AppButton (Child Widget)
Here is my AppButton.dart
And I am calling this child widget in Login.dart (Parent) like this:
AppButton(title: "Login")
Please give me a way that to set default function without making "onPress" required for it's Parent (Login.dart)
TIA
Only static value can be set as default value in constructor, so you need define you function as static like this:
class AppButton extends StatefulWidget {
final Function onPress;
const AppButton({Key? key, this.onPress = _onPress}) : super(key: key);
static void _onPress(){}
#override
State<AppButton> createState() => _AppButtonState();
}
just make it nullable:
class MyButton extends StatefulWidget {
final void Function()? onPress;
final String title;
const MyButton({Key? key, this.onPress, required this.title}) : super(key: key);
#override
State<MyButton> createState() => _MyButtonState();
}
class _MyButtonState extends State<MyButton> {
void Function() defaultOnPress = (){
// your default function here
};
#override
Widget build(BuildContext context) {
return ElevatedButton(onPressed: widget.onPress ?? defaultOnPress, child: const Text("my button"));
}
}
still you can get const constructor
you could put "static" before childOnPress()

What aspects to consider when defining attributes or methods in a stateful widget?

Below is the definition of a Stateful Widget and its associated state. As we can see, color has been defined in YellowBird and can be accessed in _YellowBirdState via the widget object.
My question is with respect to this, how do we decide where (Widget class or State class) to define the attributes? For example, color could have been defined in _YellowBirdState directly. For now, I am deciding this based on whether I have to access the attributes from outside. For example, considering the example below, if I need to access the attribute color from outside, then I define it in the Widget class.
class YellowBird extends StatefulWidget {
const YellowBird({ Key? key }) : super(key: key);
var color = 0xFFFFE306;
#override
State<YellowBird> createState() => _YellowBirdState();
}
class _YellowBirdState extends State<YellowBird> {
#override
Widget build(BuildContext context) {
return Container(color: Color(widget.color));
}
}
One reason to create the attributes in the widget class is to pass values from outside. In your example you could pass the color dynamically.
class YellowBird extends StatefulWidget {
Color color;
YellowBird(this.color, {Key? key}) : super(key: key);
#override
State<YellowBird> createState() => _YellowBirdState();
}
class _YellowBirdState extends State<YellowBird> {
#override
Widget build(BuildContext context) {
return Container(color: widget.color);
}
}
Now you can create your widget with different colors
YellowBird(Colors.green)
YellowBird(Colors.red)

How to make ValueListenableBuilder build based on a condition from UI

I have multiple ActivityButton widgets that listen to same ValueNotifier.
class ActivityButton extends StatelessWidget {
const ActivityButton({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return ValueListenableBuilder<ActivityButtonState>(
valueListenable: someModel.activityButtonStateNotifier,
builder: (_, state, __) {
return _buildContent(state);
});
}
Widget _buildContent(ActivityButtonState state) { ... }
}
I use ActivityButtonState as value for ValueNotifier.
class ActivityButtonState {
ActivityButtonState({required this.id, required this.text});
final String id;
final String text;
}
I want to scope the updates from ValueNotifier to be given to related ValueListenebleBuilder only by using id from ActivityButtonState. So, I updated constructor for ActivityButton like this:
const ActivityButton({Key? key, required this.scopeId}) : super(key: key);
final String scopeId;
Now, I don't know how to prevent rebuilds in ValueListenableBuilder if id from ActivityButtonState doesn't match scopeId in ActivityButton.
I have used Selector from provider package before. I need something similar so that build is triggered only if id matches.
Any help or alternatives appreciated.

Flutter: How can I pass values in the constructor so I can reuse my widgets?

I am quite puzzled about the values being passed in the class constructor not being available in the Widget.
I am passing the value of the cards in the widget constructor, but when debugging it and after they are build the Text widgets do not have any text.
Initializing the Widget with the values.
Debugger shows the cardValue fields with no value.
Empty Widget:
This should work:
class PockerCard extends StatefulWidget {
final String cardValue;
const PockerCard({Key key, this.cardValue}) : super(key: key);
#override
_PockerCardState createState() => _PockerCardState();
}
class _PockerCardState extends State<PockerCard> {
#override
Widget build(BuildContext context) {
return Container(
child: Text(widget.cardValue),
);
}
}

How does flutter VSCode snippets to extract widget work?

When I use VSCode snippet Extract Widget, I have the following :
class MyExtractedWidget extends StatelessWidget {
const MyExtractedWidget({
Key key,
#required T someVariable,
}) : _someVariable = someVariable,
super(key: key);
final T _someVariable;
#override
Widget build(BuildContext context){ return Container(); }
}
However, I am used to write constructors the following way :
class MyExtractedWidget extends StatelessWidget {
const MyExtractedWidget({
Key key,
#required this.someVariable, // Directly accessing variable using "this"
}) : super(key: key);
final T someVariable;
#override
Widget build(BuildContext context){ return Container(); }
}
Do you know why snippets' constructors use a temporary variable instead of directly writing in the variable?
Is it related to encapsulation? If yes, I cannot understand why, as an extracted Widget is written in the same file, and that "underscored" variables are accessible in whole file.
EDIT
I tried with another widget and I have a kind of mix :
class Test extends StatelessWidget {
const Test({
Key key,
#required List<SortedExpense> sortedExpenses,
#required this.expensesSink,
}) : _sortedExpenses = sortedExpenses, super(key: key);
final List<SortedExpense> _sortedExpenses;
final StreamSink<List<Expense>> expensesSink;
...
This is based on the privacy of the variables you're extracting.
For example, the following widget:
Text(_count.toString())
will generate:
class MyName extends StatelessWidget {
const MyName({
Key key,
#required int count,
}) : _count = count, super(key: key);
final int _count;
#override
Widget build(BuildContext context) {
return Text(_count.toString());
}
}
while this widget:
Text(count.toString())
will create:
class MyName extends StatelessWidget {
const MyName({
Key key,
#required this.count,
}) : super(key: key);
final int count;
#override
Widget build(BuildContext context) {
return Text(count.toString());
}
}