How a const widget works with its children? - flutter

Let's say I have this HomePage widget:
class HomePage extends StatelessWidget {
const HomePage({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(),
);
}
}
I am able to use a const constructor at the root (MaterialApp widget) because all children do have const constructors too.
If I add the AppBar widget, I will have to remove the const constructor from the root, because AppBar does not have a const constructor.
class HomePage extends StatelessWidget {
const HomePage({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp( // no const anymore
home: Scaffold(
appBar: AppBar(...),
),
);
}
}
But why am I able to use the HomePage widget with a const constructor ? See code below:
class App extends StatelessWidget {
const App({super.key});
#override
Widget build(BuildContext context) {
return const HomePage(); // using a const constructor
}
}
I thought it would be impossible because of the AppBar child widget.

Because the HomePage class is immutable. The build function implementation doesn't affect it.
The const keyword can be used when the object is immutable. A Compiler allocates the same portion of memory for all objects.
For more info, reference the Using constructors: Dart doc

Related

Flutter: Why the hashCodes of the following container widgets are changing eveytime I hot-reload the app (save the file)?

If I run the following application and observe the hashCodes for BuildSizedBoxWidget which I create two instances of, I notice that they are the same even when I hot reload the app. Does this mean that they are the same widget but referenced multiple times? ... But in case of BuildContainerWidget the hashCodes change every time I hot reload the app. Why does this happen?
'''
import 'package:flutter/material.dart';
void main() {
runApp(const MyApps());
}
class MyApps extends StatelessWidget {
const MyApps({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Test',
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({super.key});
final List<Widget> widgets = const [
BuildSizedBoxWidget(),
BuildSizedBoxWidget(),
BuildContainerWidget(),
BuildContainerWidget()
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('What is happening'),
),
body: Column(
children: widgets,
),
);
}
}
class BuildSizedBoxWidget extends StatelessWidget {
const BuildSizedBoxWidget({super.key});
#override
Widget build(BuildContext context) {
const Widget widget = SizedBox(height: 50, child: Text('test'));
print(widget.hashCode);
return widget;
}
}
class BuildContainerWidget extends StatelessWidget {
const BuildContainerWidget({super.key});
#override
Widget build(BuildContext context) {
Widget widget = Container(height: 50, color: Colors.red);
print(widget.hashCode);
return widget;
}
}
'''
The variables defined in the body of the build method will be re-initialized during SetState.
Variables specified by the const keyword are not initialized.
There are only three parameters required by SizeBox Widget, and all of them can be initialized.
But Container Widget contains many parameters that cannot be initialized. So Container cannot be specified with the const keyword
If you put them outside the body of the build method, the HasCode will not change
class BuildContainerWidget extends StatelessWidget {
BuildContainerWidget({super.key});
Widget widget = Container(key: Key('value'), height: 50, child: Text('test'));
#override
Widget build(BuildContext context) {
print(widget.hashCode);
return widget;
}
}

Reusuable Stateless Widgets

I am creating reusable stateless widget for troubleshooting and maintenance. MyApp1 is a statelesswidget and am calling this widget MyApp1(title: 'title',) from a statefull widget.In order to segregate many lines of code and make troubleshooting simpler, another widgets firstone and Secondone are created. Here am passing a title data. I made two widgets firstone (widget function) and SecondOne (Statelesswidget). Although I am showing a text in both, the outcome differs.
class MyApp1 extends StatelessWidget {
final String title;
const MyApp1({super.key,required this.title});
#override
Widget build(BuildContext context) {
return MaterialApp(
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Column(
children: [
Text(title,style: Theme.of(context).textTheme.titleLarge),
firstone(context),
SecondOne(title: 'title'),
],
),
),
);
}
Widget firstone(context){
return Text(title,style: Theme.of(context).textTheme.titleLarge);
}
}
class SecondOne extends StatelessWidget {
final String title;
const SecondOne({Key? key,required this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text(title,style: Theme.of(context).textTheme.titleLarge);
}
}
Although the text styles are identical in both, my output is different. I don't have to supply the title data twice when using firstone (the widget function). Which is preferable: Stateless widgets or widget functions? If I use a stateless widget, I transmit data from a stateful widget to Myapp1 stateless widget and then to a second widget. Is this correct
My Output:
Classes should be preferred over functions that return widgets.
It's different because you're manually passing a BuildContext which is provided above the scope of where the default ThemeData can be accessed from (is provided by MaterialApp).
class MyApp1 extends StatelessWidget {
final String title;
const MyApp1({super.key,required this.title});
#override
Widget build(BuildContext context) { // <- this BuildContext is being used
return MaterialApp( // <- this widget provides the `ThemeData`, which isn't accessible from the above context
title: title,
home: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Column(
children: [
Text(title,style: Theme.of(context).textTheme.titleLarge), // <- refers to the `context` provided by build above
firstone(context), // <- refers to the `context` provided by build above
SecondOne(title: 'title'),
],
),
),
);
}
Widget firstone(context){
return Text(title,style: Theme.of(context).textTheme.titleLarge);
}
class SecondOne extends StatelessWidget {
final String title;
const SecondOne({Key? key,required this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
// This uses the correct context, inherited from `MaterialApp` properly.
return Text(title,style: Theme.of(context).textTheme.titleLarge);
}
}
Please do not return MaterialApp .
Direct return column in myapp1 class.
It will solve your issue

Segmenting the elements of homepage in multiple >dart files

Being new to Flutter I want to know if it is a good practice to segregate the elements of Any page like HOME to different Classes or DART files.
If the answer is positive, I need some help with that.
I am aware that I have to Include the pages in both Mother and daughter .dart pages to each other.
Where I am confused is how much should I mention for a part of a page. (please forgive my nativity if there any)
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AppName',
home: MyHomePage(),
);
What should I return?
The Material App already runs the Mother or main page so how much to be included?
Or should I just Code the elements Like Row and Column and Card etc...
If the latter is true then how should I call them? Will those be automatically called when The MAIN .dart is executed?
~Addition~
Can I return any Layout Widget(Row/Column/Card) out of nothing !!
like
class MyHomePage extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
(I think it is logical because all the queries will be ultimately forwarded to MAIN.dart)
Any help is appreciated.
If I understand your question correctly, let me answer with an example:
Say your main.dart is as follows:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'AppName',
home: MyHomePage(),
);
}
}
and your home_page.dart is:
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("AppName"),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
CustomWidget1(),
CustomWidget2(),
],
),
);
}
}
Then CustomWidget1 can be (in a file named custom_widget_1.dart):
class CustomWidget1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Center(
child: Text("CustomWidget1"),
);
}
}
Then CustomWidget2 can be (in a file named custom_widget_2.dart):
class CustomWidget2 extends StatefulWidget {
CustomWidget2({Key key}) : super(key: key);
#override
_CustomWidget2State createState() => _CustomWidget2State();
}
class _CustomWidget2State extends State<CustomWidget2> {
#override
Widget build(BuildContext context) {
return Center(
child: Text("CustomWidget2"),
);
}
}
Yes you can create many directories and arrange your Dart files in it like services, model and config. As you call the main.dart the other Classes will not certainly be on main.dart, let me put this this way, maon.dart = >homepage.dart => productPage.dart=>.......
it is just navigation while navigation to some parameters classes be sure to parse the parameters

How to call a Stateless widget in MyApp's build method whose state is managed by its Stateful Parent

I was following flutter tutorials for managing state of a widget from its parent on this link [https://flutter.dev/docs/development/ui/interactive#parent-managed][1]
and i cant figure out how would call the widget in this case
it is very simple once you get the logic.
In practice, the parent (the "true" widget that you call), i.e.
class ParentWidget extends StatefulWidget {
#override
_ParentWidgetState createState() => _ParentWidgetState();
}
is the one that you call wherever and whenever you want in the rest of the code.
Since this is a Stateful widget, it means that it has stated (to keep it simple, it will manage any changes on the UI). Any change will occur, It will be changing its state and so, this code:
class _ParentWidgetState extends State<ParentWidget> {
bool _active = false;
void _handleTapboxChanged(bool newValue) {
setState(() {
_active = newValue;
});
}
#override
Widget build(BuildContext context) {
return Container(
child: TapboxB(
active: _active,
onChanged: _handleTapboxChanged,
),
);
}
}
Anyhow, once you use a Stateful widget, you change its state whenever you want to call the function
setState(() {
oldValue= newValue;
});
It will rebuild the entire widget changing the stuff you want (such as texts, images, widgets, and so on).
In a non-proper way, consider it as a particular widget that can change its UI during the time.
if you want to call it in MyApp's build method you will have to make MyApp a stateful widget so that it can manage the state of the said widget
void main() => runApp(MyApp());
//we make MyApp to be a stateful widget
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
//we define the state which will be used in the widget here
var myState = "something";
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
body: Center(
child: Container(
//the data used by MyWidget is managed by MyApp which is a statefull widget.
child: MyWidget(state: myState),
),
),
),
);
}
}
Or rather wrap your widget with another stateful widget which you will use in MyApp's build method
//we create a widget which will manage the state of its children class MyStateManagingWidget extends StatefulWidget { #override
_MyStateManagingWidgetState createState() => _MyStateManagingWidgetState(); }
class _MyStateManagingWidgetState extends State<MyStateManagingWidget> { var myState = "some state"; #override Widget build(BuildContext context) {
//we put our widget who's state is to be managed here
return MyWidget(); } }
class MyApp extends StatelessWidget { #override Widget build(BuildContext context) {
return MaterialApp(
title: 'Material App',
home: Scaffold(
appBar: AppBar(
title: Text('Material App Bar'),
),
body: Center(
child: Container(
//we now use the state managing widget here
child: MyStateManagingWidget()),
),
),
); } }

What is the difference between returning a Widget with and without the "new" keyword in flutter? e.g return Container() and return new Container()

In flutter we are able to return a widget with and without the new keyword. So what is the difference between
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Container(),
);
}
}
which has MaterialApp() and Container() constructor without the new keyword
and
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Container(),
);
}
}
which has new MaterialApp() and new Container() constructor with the new keyword
It does the same thing. From dart2, new keyword is optional