Welcome to follow the official wechat account: FSA Full stack action 👋
1. Program entry
Generally, the main entrance to a Flutter is main.dart.
1. The nature of the interface (Widgets)
Start a Flutter interface with the runApp function in main. The Widget app received by runApp is the interface, i.e. the interface is a Widget:
main() {
runApp(Center(
child: Text("Hello world",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 30, color: Colors.orange)),
));
}
Copy the code
In Flutter, all interfaces and controls are widgets
2, MaterialApp
To quickly develop a standard Material interface, The MaterialApp Widget is provided by Flutter:
import 'package:flutter/material.dart';
main() {
// 1. RunApp function
runApp(MaterialApp(
/ / debugShowCheckedModeBanner: false, / / control interface whether the upper right corner of the display ` debug ` hints
home: Scaffold(
appBar: AppBar(
title: Text("The first Flutter program"),
),
body: Center(
child: Text(
"Hello World",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 30, color: Colors.orange),
),
),
),
));
}
Copy the code
Scaffolding is a Widget that translates as scaffolding to help developers build interfaces with appBars
Second, the State of the Widget
Flutter, everything based on widgets, divides widgets into two categories:
StatelessWidget
: stateless Widget that determines that no state (data) changesStatefulWidget
: stateful Widget that has some data that needs to change during runtime
1, StatelessWidget
In the above demo, the runApp(Widget App), MaterialApp({this.home}) and Scaffold({this.body}) methods all receive the Widget type parameters and do not save the state. So you can split them into three statelessWidgets to avoid nesting hell:
This approach of extracting widgets is similar to component-development in a large front end
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false, home: HomePage(), ); }}class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("The first Flutter program"), ), body: ContentBody(), ); }}class ContentBody extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
"Hello World",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 30, color: Colors.orange), ), ); }}Copy the code
Quick template creation with State Widget in AndroidStudio:
- Stless: Enter stless to generate the StatelessWidget
- Stful: Type stful to generate the StatefulWidget directly
2, StatefulWidget
Flutter is declaratively developed, meaning that the interface automatically changes when a state changes, in this case the state is data. A StatefulWidget is a Widget that can be stateful. A simple example is to write a consent control:
/// State flag:
/// Stateful could not define State -> create a separate State class which was responsible for maintaining State
class ContentBody extends StatefulWidget {
@override
State<StatefulWidget> createState() {
returnContentBodyState(); }}/// Use the State class to hold the State
class ContentBodyState extends State<ContentBody> {
var flag = true;
@override
Widget build(BuildContext context) {
return Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Checkbox(
value: flag,
onChanged: (value) {
/// flag = value; // Invalid code will not refresh the interface
/// The setState() method must be used to force an interface refresh
setState(() {
flag = value;
});
},
),
Text("Consent agreement", style: TextStyle(fontSize: 20)),,),); }}Copy the code
Note:
- The concept of State in Flutter is the same as that in React.
- You can’t just modify the data, you have to call it
setState()
The notification screen must be redrawn on the next frame.
3. Why can’t the State Widget itself define State?
Whether a StatelessWidget or a StatefulWidget, its parent class is a Widget.
@immutable
abstract class Widget extends DiagnosticableTree {... }Copy the code
Widgets have the @immutable annotation, which means that all subclasses of widgets, even if they have member attributes, must use final variables.
/// State cannot be defined in any Widget class, and class member attributes must be final
class ContentBody extends StatelessWidget {
// IDE error: This class (or a class that this class inherits from) is marked as '@immutable', but one of more of its instance fields aren't final: ContentBody.flag
// Error code
// for @immutable annotated classes, member attributes must be final
var flag = true;
@override
Widget build(BuildContext context) {
return Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Checkbox(value: flag, onChanged: (value) => flag = value),
Text("Consent agreement", style: TextStyle(fontSize: 20)),,),); }}Copy the code
3. Comprehensive cases
1. StatelessWidget Integrated Case (List of Items)
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
returnMaterialApp( home: HomePage(), ); }}class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("List of Goods"), ), body: HomeContent(), ); }}class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Column will cross the relayoutBoundary and change to ListView
return ListView(
children: [
HomeProductItem("Apple1"."Macbook1"."https://tva1.sinaimg.cn/large/006y8mN6gy1g72j6nk1d4j30u00k0n0j.jpg"),
SizedBox(height: 6),
HomeProductItem("Apple2"."Macbook2"."https://tva1.sinaimg.cn/large/006y8mN6gy1g72imm9u5zj30u00k0adf.jpg"),
SizedBox(height: 6),
HomeProductItem("Apple3"."Macbook3"."https://tva1.sinaimg.cn/large/006y8mN6gy1g72imqlouhj30u00k00v0.jpg"),]); }}class HomeProductItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
final style1 = TextStyle(fontSize: 25, color: Colors.orange);
final style2 = TextStyle(fontSize: 20, color: Colors.green);
HomeProductItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
border: Border.all(
width: 5.// Set the width of the border
color: Colors.pink, // Set the color of the border
),
),
child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.end,
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Text(title, style: style1, textAlign: TextAlign.center),
Text(title, style: style1),
SizedBox(height: 8),
Text(desc, style: style2),
SizedBox(height: 8), Image.network(imageURL), ], ), ); }}Copy the code
2. Comprehensive Case of StatefulWidget (Counters)
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
returnMaterialApp( home: HomePage(), ); }}class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("title")),
body: HomeContent("hello world")); }}/// Why is the build method of the StatefulWidget in State when Flutter is designed
/// 1.Build widgets that depend on variables in State (State/data)
/// 2.During the operation of Flutter:
/// Widgets are constantly destroyed and created
/// We don't want to create a new State when our own State changes
class HomeContent extends StatefulWidget {
final String message;
HomeContent(this.message);
@override
_HomeContentState createState() => _HomeContentState();
}
class _HomeContentState extends State<HomeContent> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_getButtons(),
Text("Current count:$_counter", style: TextStyle(fontSize: 25)),
Text("The message:${widget.message}")],),); } Widget _getButtons() {return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
child: Text("+", style: TextStyle(fontSize: 20)),
style: TextButton.styleFrom(backgroundColor: Colors.pink),
onPressed: () {
setState(() {
_counter++;
});
},
),
ElevatedButton(
child: Text("-", style: TextStyle(fontSize: 20)), style: TextButton.styleFrom(backgroundColor: Colors.purple), onPressed: () { setState(() { _counter--; }); },),,); }}Copy the code
4. Life cycle
1. The life cycle of StatelessWidget
Since the StatelessWidget has no state, its life cycle is simple: call the constructor, then call build(), and no more:
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
returnMaterialApp( home: HomePage(), ); }}class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("title")),
body: HomeContent("hello world")); }}// The lifecycle of the StatelessWidget
class HomeContent extends StatelessWidget {
final String message;
HomeContent(this.message) {
print("Constructor called");
}
@override
Widget build(BuildContext context) {
print("Call build method");
returnText(message); }}Copy the code
Log output:
I/flutter (3092): constructor called I/flutter (3092): call build methodCopy the code
2. Lifecycle of StatefulWidget
methods | instructions |
---|---|
createState | Framework will by calling StatefulWidget. CreateState to create a State. |
initState | The newly created State will be associated with a BuildContext where State is considered installed and initState will be called. In general, we can rewrite this function to initialize it. |
didChangeDependencies | This function is called after the initState call. In fact, this function is always called by the Framework when the dependency of the State object changes. |
build | After the above steps, the system decides that a State is ready and calls Build to build the view. We need to return a Widget in this function. |
deactivate | Deactivate This function is called when State is temporarily removed from the view tree. It is also called when the page switches, because State’s position in the view tree changes and needs to be temporarily removed before being added. |
dispose | The Framework calls this function when State is permanently removed from the view tree. Triggered before destruction, we can do the final resource release here. The deactivate function is always called before calling this function. |
didUpdateWidget | This function is called when the configuration of the Widget changes. For example, this function is called when hot overloading occurs. After calling this function, the build function is called. |
setState | When you need to update the view of State, you need to call this function manually, which triggers the build function. |
- Methods that extract to: www.cxybcw.com/45008.html
- The official documentation (full) : API. Flutter. Dev/flutter/wid…
// StatefulWidget's life cycle
class HomeContent extends StatefulWidget {
HomeContent(String message) {
print(1. Call the constructor method of HomeContent);
}
@override
_HomeContentState createState() {
print("2. Call the createState method of HomeContent");
return_HomeContentState(); }}class _HomeContentState extends State<HomeContent> {
_HomeContentState() {
print(3. Call the constructor method of _HomeContentState);
}
@override
void initState() {
// Note: super(@mustcallsuper) must be called
super.initState();
print("4. Call the initState method of _HomeContentState");
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
print("Call the didChangeDependencies method of _HomeContentState");
}
@override
void didUpdateWidget(covariant HomeContent oldWidget) {
super.didUpdateWidget(oldWidget);
print("Call the didUpdateWidget method of _HomeContentState");
}
@override
Widget build(BuildContext context) {
print("5. Call the build method of _HomeContentState");
return Container();
}
@override
void dispose() {
super.dispose();
print("6. Call the dispose method of _HomeContentState"); }}Copy the code
Log result:
// Interface initializes I/flutter (3092): 1. Call the HomeContent constructor method I/flutter (3092): 2. Call HomeContent createState method I/flutter (3092): 3. Call the constructor method I/flutter (3092): 4. Call the initState method I/flutter (3092) of _HomeContentState: Call the didChangeDependencies method I/ FLUTTER (3092) of _HomeContentState: 5. Call the build method of _HomeContentState // click the count button I/ FLUTTER (3092): 5. Call the build method of _HomeContentStateCopy the code
Logs in Dispose () are not printed because the Widget is not removed in the Demo here