這個轉自我自己的有道雲 想看圖檔去那裡
文檔:Day3_2 StatelessWidget 和 StatefulWi…
連結:http://note.youdao.com/noteshare?id=71abe63a08ed806e44911f636b452b44&sub=AC2B27FCC2AA41FE86AB93B15475B063
StatelessWidget 和 StatefulWidget
- StatelessWidget 的案例
- StatefulWidget 的案例
- StatefulWidget的生命周期
1. StatelessWidget
我們經過之前的練習知道了, 這個東西是無狀态的Widget, 他的資料是不能變的
StatelessWidget練習
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-rzraKNvW-1583548791492)(4DAC89A36141444591BDE15A137B9CC5)]
我們從頭寫起
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container();
}
}
然後把架構搭好
- 我們發現直接寫extends StatelessWidget速度太慢, 是以這裡可以使用一個快速的寫法
- 我們寫出stl 然後回車就可以快速打出 對應的繼承代碼
- 但是我們要使用material的樣式而且要展示home界面是以需要這樣嵌套
Scaffold 這個東西就像Android中的Activity 是一樣的
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage()
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("StatelessWidget練習")
),
body: HYHomeList(),
);
// 注意這裡和java 那些東西不一樣需要加分号
}
}
class HYHomeList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ;
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-IQuy2NTk-1583548791494)(D1785F6E751A4EA58D078E59808124EE)]
然後我們觀察這個項目的結構
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-hHjZXyaw-1583548791496)(93E9474DD60046048B3C898ACE94CA6F)]
我們先寫出架構
- 因為我們這裡是從上往下放多個是以這裡是Column
- 如果是放多個就是children, 放一個就是child
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage()
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("StatelessWidget練習")
),
body: HYHomeList(),
);
// 注意這裡和java 那些東西不一樣需要加分号
}
}
class HYHomeList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text("hahah"),
Text("hahha"),
Text("hahaha")
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-TTcdlZnL-1583548791496)(4187A953B1F14A46AFDD2E12ECFEA8C6)]
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-HIOeRhl7-1583548791497)(93E9474DD60046048B3C898ACE94CA6F)]
這個裡面也是一個Column
HYHomeListItem 的設計
- 因為這個很明顯, 他需要顯示不同的内容
- 我們flutter是一個面向對象的語言
是以我們的Widget可以設定成要傳參數的那種
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage()
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("StatelessWidget練習")
),
body: HYHomeList(),
);
// 注意這裡和java 那些東西不一樣需要加分号
}
}
class HYHomeList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/celve/2019-03-04/55ce1f75dac4b12a4aae1ec691b83400.jpg")
],
);
}
}
class HYHomeListItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
HYHomeListItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(title),
Text(desc),
Image.network(imageURL)
],
);
}
}
是以這個裡面也是item Widget
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-vG7qnv4P-1583548791497)(70C3F731820246E7ADC926AA5AE6A1C2)]
但是下面報錯了
A RenderFlex overflowed by 285 pixels on the bottom.
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-8uKNOSol-1583548791498)(2C12B763EB14423AA00843860FD9CEC9)]
意思是說超出了, 我們的Widget超出了螢幕的範圍
我們換用ListView代替最外面的Column, 讓最外面可以滾動這個問題就可以解決了
import 'package:flutter/material.dart';
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage()
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("StatelessWidget練習")
),
body: HYHomeList(),
);
// 注意這裡和java 那些東西不一樣需要加分号
}
}
class HYHomeList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/celve/2019-03-04/55ce1f75dac4b12a4aae1ec691b83400.jpg")
],
);
}
}
class HYHomeListItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
HYHomeListItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(title),
Text(desc),
Image.network(imageURL)
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-K1Vlbhnt-1583548791499)(0D7949F3C6174E9CA7E2DAFCA985B5A3)]
但是如果我們不希望你居中
- 這個時候我們可以設定itemWidget中的Column交叉軸屬性
但是這個不是一般的做法
class HYHomeListItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
HYHomeListItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text(title),
Text(desc),
Image.network(imageURL)
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-6Kp0vHDe-1583548791499)(CEB3740EDFFA40BFBC904B41995AF078)]
這樣我們就可以居左居右了
- 但是如果你想title居左 desc居右 那我們就需要在裡面再嵌入Row讓裡面的東西可以自行設定他的居左居右
- 注意這個Row是占據一整行的
這個就是一般做法
class HYHomeListItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
HYHomeListItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(title),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(desc),
],
),
Image.network(imageURL)
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-5E7i9OH3-1583548791500)(42F45FFB5A8F4AAF97CBB0D7B7292AFC)]
調整樣式
class HYHomeListItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
HYHomeListItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(title, style: TextStyle(fontSize: 30, color: Colors.red),),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(desc, style: TextStyle(fontSize: 20, color: Colors.blue)),
],
),
Image.network(imageURL)
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-OSjgRgGM-1583548791500)(53C41C5F1A61452CA6364E5469558B1E)]
設定外邊距
然後我如果希望這些Widget間有些間距的話我們可以使用SizedBox
- 一般來說如果我們使用的是html那種東西的話, 我們因該是設定類似于margin-top 之類的東西
- 但是在flutterz中我們沒有這種東西
- 是以我們為了撐高度使用的是SizedBox(height: number)
- 如果想要左右邊距的話我們使用Alignment就可以了
因為flutter中萬物皆Widget是以margin 這種也是屬于Widget的(當然有些是屬于widget的屬性的)
class HYHomeList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
children: <Widget>[
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
SizedBox(height: 10),
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
SizedBox(height: 10),
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/celve/2019-03-04/55ce1f75dac4b12a4aae1ec691b83400.jpg")
],
);
}
}
class HYHomeListItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
HYHomeListItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(title, style: TextStyle(fontSize: 30, color: Colors.red),),
],
),
SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(desc, style: TextStyle(fontSize: 20, color: Colors.blue)),
],
),
SizedBox(height: 8),
Image.network(imageURL)
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-NhdSW4xF-1583548791501)(F5D7CDE5D2364A4DB592BAC917707F2F)]
設定内邊距
如果我們覺得這個東西挨着邊框不好看
那麼我們可以設定他的padding
這個東西padding: EdgeInsets.all(8) 直接在ListView上面加
class HYHomeList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListView(
padding: EdgeInsets.all(8),
children: <Widget>[
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
SizedBox(height: 10),
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
SizedBox(height: 10),
HYHomeListItem("title", "desc", "https://www.lianaiyx.com/d/file/celve/2019-03-04/55ce1f75dac4b12a4aae1ec691b83400.jpg")
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-d1KU53zu-1583548791502)(435875AA074941298D05F5D119E78BE3)]
設定邊框
然後我們覺得這個還是有一個邊框比較好
這個東西因該加在item上面但是item沒有這個屬性
- 邊框這個東西需要Container來設定, 其實就是一個普通的Widget
- 因為Column是裝多個widget給他設定border肯定不合适
- 這裡我們使用alt + enter 加上container包裹的快捷鍵
- 然後設定Container的border
class HYHomeListItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
HYHomeListItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
border: Border.all(
width: 5,
color: Colors.red
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Text(title, style: TextStyle(fontSize: 30, color: Colors.red),),
],
),
SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(desc, style: TextStyle(fontSize: 20, color: Colors.blue)),
],
),
SizedBox(height: 8),
Image.network(imageURL)
],
),
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-ifyRVLwW-1583548791502)(7C13287C51C046158B01D00FF54A0653)]
StatalessWidget完整代碼
import 'package:flutter/material.dart';
main() => runApp(MyApp());
//直接寫效率太低了
//我們直接敲stl就會生成對應的代碼
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: HYHomePage(),
// 這個就是一啟動顯示的頁面
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("商品清單")
),
body: HYHomeContent(),
);
}
}
class HYHomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
// 現在隻是想回顧一下這個StatelessWidget
return ListView(
// 要放多個 是以是children 不是 child
children: <Widget>[
// 我們因該在裡面放商品資料
// The specific RenderFlex in question is: RenderFlex#af73a relayoutBoundary=up1 OVERFLOWING
// 這個是操作布局邊界 希望讓它變成可滾動的區域
HYHomeProductItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-04-22/b0201606065bcdad3159cd02c9199a01.jpg"),
SizedBox(height: 6),
HYHomeProductItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-07-27/c4d6ea4d8c51e0aa3c750aed13913a1b.jpg"),
SizedBox(height: 6),
HYHomeProductItem("title", "desc", "https://www.lianaiyx.com/d/file/GalGame/2019-03-05/6c815fb726391c117d1d6b0a126fa643.jpg"),
],
);
}
}
//我們使用同一個Widget但是我們希望展示的東西是不一樣的
//
class HYHomeProductItem 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);
HYHomeProductItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
// 我們現在想要設計一個邊框
// 如果想要包裹一個widget我們可以使用alt + enter
return Container(
// 如果我們希望和裡面的東西有一個内邊距
padding: EdgeInsets.all(12),
// decoration這個東西是一個抽象類
decoration: BoxDecoration(
// ctrl + alt + B 就可以看到它的實作類
border: Border.all(
// 這個東西就是設定邊框的寬度
width: 5,
// 設定邊框顔色
color: Colors.black12
// 這個12是一個透明度的意思
)
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
// 但是實際上我們因該通過 交叉軸而是在裡面嵌套 Row然後在裡面
children: <Widget>[
// 我們想要居右
// , textAlign: TextAlign.right 這個沒有用 文本是包裹内容的是以居左居右
// 這個東西是Column是以我們設定的是它的交叉軸
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text(title, style: style1, textAlign: TextAlign.right),
],
),
// flutter沒有margin-top之類的東西是以
SizedBox(height: 8),
Row(
children: <Widget>[
Text(desc, style: style2),
],
),
// 這個八個像素 但是是和裝置有關系
// 後面
// 如果是想要左右邊距離的話Alignmen就可以了
SizedBox(height: 8),
Row(
children: <Widget>[
Image.network(imageURL)
],
)
],
),
);
}
}
2. StatefulWidget的使用示例
- 為什麼flutter在設計的時候StatefulWidget的build方法放在State中
- build出來的Widget是需要以來State中的變量(狀态)
- flutter運作過程中Widget是不斷銷毀建立的 Element-Render-Object
- 當時我們狀态發生改變的時候, 并不希望建立一個新的State
是以我們呢才會将StatefulWidget和State實作類分離
執行個體
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-ZVuEUKM7-1583548791502)(1FF62F62A746427D8D1194B6D6714C51)]
- 首先我們搭建出平台
import "package:flutter/material.dart";
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return HYHomePage();
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomeContent(),
);
}
}
class HYHomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("statefulWidget示例"),
),
body: Text("test")
);
}
}
如果我們要做計數器很明顯我們需要具有狀态的Widget
是以就需要用StatefulWidget
import "package:flutter/material.dart";
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage(),
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("statefulWidget示例"),
),
body: Text("test")
);
}
}
class HYHomeContent extends StatefulWidget {
@override
_HYHomeContentState createState() => _HYHomeContentState();
}
class _HYHomeContentState extends State<HYHomeContent> {
@override
Widget build(BuildContext context) {
return Container();
}
}
然後就是結構和StatelessWidget不同是的我們的渲染的架構是在繼承StatefulWidget, 因該是寫在State裡面
import "package:flutter/material.dart";
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage(),
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("statefulWidget示例"),
),
body: Center(child:HYHomeContent())
);
}
}
class HYHomeContent extends StatefulWidget {
@override
_HYHomeContentState createState() => _HYHomeContentState();
}
class _HYHomeContentState extends State<HYHomeContent> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.red,
child: Text("+", style: TextStyle(color: Colors.white)),
onPressed: () {
},
),
RaisedButton(
color: Colors.green,
child: Text("-", style: TextStyle(color: Colors.white)),
onPressed: () {
},
)
],
),
Text("counter: $_counter")
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-TshD7TJE-1583548791503)(236D8204F87B4A6283A0CD5579F74810)]
但是我們直接改變變量的值還是不行的
- 我們必須要調用setState重新整理
- 這個東西就是調用重新整理頁面的意思, 是以你如果把變量的改變寫在前面寫在後面都是一樣的
- 再強調一遍私有屬性是會加_ 加了隻有這個變量就會隻屬于這個 庫
- 這個注意 這裡如果要分離State的作為一個新的widget則是是需要将我們的函數作為閉包傳過去 然後在那邊調用
import "package:flutter/material.dart";
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage(),
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("statefulWidget示例"),
),
body: Center(child:HYHomeContent())
);
}
}
class HYHomeContent extends StatefulWidget {
@override
_HYHomeContentState createState() => _HYHomeContentState();
}
class _HYHomeContentState extends State<HYHomeContent> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.red,
child: Text("+", style: TextStyle(color: Colors.white)),
onPressed: () {
++_counter;
setState(() {
});
},
),
RaisedButton(
color: Colors.green,
child: Text("-", style: TextStyle(color: Colors.white)),
onPressed: () {
setState(() {
--_counter;
});
},
)
],
),
Text("counter: $_counter")
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-fvcLFTYQ-1583548791503)(6C3739A610094A2F8631AC662BDBC587)]
我們看到源碼裡面其實它也是在setState裡面調了傳進去的參數的
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-aTQ4ALCN-1583548791504)(04E6A1BEBEDD4139A8BCC168D705E8AD)]
指向StatefulWidget的指針
還有如果你想要再StatefulWidget中傳參數 然後再後面展示
可以再傳的方式 也可以用state指向StatefulWidget對象的指針來實作這個功能
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("statefulWidget示例"),
),
body: Center(child:HYHomeContent("傳遞的參數"))
);
}
}
class HYHomeContent extends StatefulWidget {
final String message;
HYHomeContent(this.message);
@override
_HYHomeContentState createState() => _HYHomeContentState();
}
class _HYHomeContentState extends State<HYHomeContent> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
color: Colors.red,
child: Text("+", style: TextStyle(color: Colors.white)),
onPressed: () {
++_counter;
setState(() {
});
},
),
RaisedButton(
color: Colors.green,
child: Text("-", style: TextStyle(color: Colors.white)),
onPressed: () {
setState(() {
--_counter;
});
},
)
],
),
Text("counter: $_counter ${widget.message}")
],
);
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-tKOKjZkB-1583548791505)(79250287C7004999B1970578F4AACF0D)]
3. StatfulWidget和StatelessWidget的生命周期函數
- 生命周期函數也被稱為“hook” “鈎子函數”
- 其主要功能就是在程式運作到指定位置時進行回調
- 生命周期函數的功能
- 初始化一些資料, 變量, 狀态
- 發送網絡請求
- 監聽元件中的事件 controller 添加監聽事件(滾動事件)
- 管理記憶體: 一些定時器-controller手動進行銷毀
StatelessWidget的生命周期函數很簡單
主要就是StatelessWidget構造函數和build函數
其實就是沒有專門的生命周期函數, 因為它沒有狀态, 是以它也簡單的多
import "package:flutter/material.dart";
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage()
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("title")
),
body: HYHomeContent()
);
}
}
class HYHomeContent extends StatelessWidget {
HYHomeContent() {
print("HYHomeContent 構造函數執行");
}
@override
Widget build(BuildContext context) {
print("HYHomeConten build函數執行");
return Text("content");
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-XxPaQwMg-1583548791505)(530E35C0AA264130B6EC3915933ECDE0)]
StatefulWidget的生命周期函數
重要
先建立一個簡單的StatefulWidget
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-ip2UwgJp-1583548791505)(5CF4FCB23BB740C7A6855B909120D2CB)]
import "package:flutter/material.dart";
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage()
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("StatefulWidget的生命周期函數")
),
body: HYHomeContent()
);
}
}
class HYHomeContent extends StatefulWidget {
@override
_HYHomeContentState createState() => _HYHomeContentState();
}
class _HYHomeContentState extends State<HYHomeContent> {
int _counter = 0;
// 如果我們想要拆分這個東西因該怎麼辦
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
child: Text("+"),
onPressed: () {
setState(() {
_counter++;
});
},
),
Text("counter: $_counter")
],
);
}
}
然後将生命周期函數寫上去
- StatefulWidget子類的構造方法
- StatefulWidget子類的createState方法
- State子類的構造方法
- State子類的initState方法
- State子類的build方法
- State子類的dispose方法
import "package:flutter/material.dart";
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage()
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("StatefulWidget的生命周期函數")
),
body: HYHomeContent()
);
}
}
class HYHomeContent extends StatefulWidget {
HYHomeContent() {
print("1. 調用HYHomeContent的構造函數");
}
@override
_HYHomeContentState createState() {
print("2. 調用HYhomeContent的createState方法");
return _HYHomeContentState();
}
}
class _HYHomeContentState extends State<HYHomeContent> {
int _counter = 0;
_HYHomeContentState() {
print("3. 調用_HYHomeContentState的構造函數");
}
@override
void initState() {
// TODO: implement initState
print("4. 調用_HYHomeContentState的initState方法");
// 下面這個必須寫
super.initState();
}
// 如果我們想要拆分這個東西因該怎麼辦
@override
Widget build(BuildContext context) {
print("5. 調用_HYHomeContentState的build方法");
return Column(
children: <Widget>[
RaisedButton(
child: Text("+"),
onPressed: () {
setState(() {
_counter++;
});
},
),
Text("counter: $_counter")
],
);
}
@override
void dispose() {
// TODO: implement dispose
print("6. 調用_HYHomeContentState的dispose方法");
super.dispose();
}
}
後面這個反複調用是Android Studio 的bug, vscode就沒有
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-mqD1bPq3-1583548791506)(B0C29EE84CBF40A4B8090FBCF3943420)]
- 在我們點選+以後 會不停的調用build
- 這個過程其實也就是不停重建Widget過程
- 這個也是驗證了Widget是不停的銷毀和建立的
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-1dshXOXz-1583548791506)(F25C1882E1ED4A8DB29BD6B0A6EFAEA8)]
還有一些其他的生命周期函數那些不是很常用但是還是需要知道
import "package:flutter/material.dart";
main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HYHomePage()
);
}
}
class HYHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("StatefulWidget的生命周期函數")
),
body: HYHomeContent()
);
}
}
class HYHomeContent extends StatefulWidget {
HYHomeContent() {
print("1. 調用HYHomeContent的構造函數");
}
@override
_HYHomeContentState createState() {
print("2. 調用HYhomeContent的createState方法");
return _HYHomeContentState();
}
}
class _HYHomeContentState extends State<HYHomeContent> {
int _counter = 0;
_HYHomeContentState() {
print("3. 調用_HYHomeContentState的構造函數");
}
@override
void initState() {
// TODO: implement initState
print("4. 調用_HYHomeContentState的initState方法");
// 下面這個必須寫
super.initState();
}
@override
void didUpdateWidget(HYHomeContent oldWidget) {
// TODO: implement didUpdateWidget
print("調用——HYHomeContentState的didUpdateWidget方法");
super.didUpdateWidget(oldWidget);
}
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
// 這個數據依賴一些東西的時候 依賴的東西改變了就會調用
// 就是裏面的東西 假如依賴了 InheritedWidget的message 假如這個改變了
// 就會調用didChangeDependecies
print("調用_HYHomeContenState的didChangeDepancies");
super.didChangeDependencies();
}
// 如果我們想要拆分這個東西因該怎麼辦
@override
Widget build(BuildContext context) {
print("5. 調用_HYHomeContentState的build方法");
return Column(
children: <Widget>[
RaisedButton(
child: Text("+"),
onPressed: () {
setState(() {
_counter++;
});
},
),
Text("counter: $_counter")
],
);
}
@override
void dispose() {
// TODO: implement dispose
print("6. 調用_HYHomeContentState的dispose方法");
super.dispose();
}
}
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-WtZcALT6-1583548791507)(B51E30A28D63489492042D24E7DF0BA4)]