main()
函数为入口,通过runApp()
函数进入到Flutter框架的应用,实现界面的展示和交互,如果不调用runApp()
函数,那么所执行的就是一个Dart控制台应用,屏幕上什么也不会显示。runApp()
进入,函数接受给定的widget并使其成为widget树的根;StatelessWidget
中设置MaterialApp
确立APP设计风格,主题;StatefulWidget
的State
,来更改界面状态和响应用户操作;Scaffold
来进行布局。//runApp进入程序
void main() => runApp(new MyApp());
//无状态widget
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
//MaterialAPP可设置主题和起始页
return new MaterialApp(
home: new MyHomePage(),//此属性页面也全屏
);
}
}
class MyHomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return new MyHomePageState();
}
}
class MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(//实现了基本的布局结构
appBar: new AppBar(),
body: 需求widget,
);
}
}
这是一个不可改变状态的部件,它通过构建一个更具体的描述用户界面的的其他小部件集群来描述用户界面的一部分,构建过程通过递归进行,知道用户界面的描述完全完成。
当用户界面不依赖对象本身的配置信息以外的任何内容以及widget自身变化而变化时,无状态widget是很好用的,但对于动态更改的组合,还是要使用有状态的widget。
此类之所以无状态是因为,widget本身状态就是不可变的,仅支持一帧,在创建时,内部调用createElement()
创建一个无状态的元素。
StatelessWidget:
abstract class StatelessWidget extends Widget {
const StatelessWidget({ Key key }) : super(key: key);
/// Creates a [StatelessElement] to manage this widget's location in the tree.
//系统调用。创建一个无状态元素来管理这个这个widget在widget树中的位置
@override
StatelessElement createElement() => StatelessElement(this);
//子类复写此方法传入一个widget
@protected
Widget build(BuildContext context);
}
StatelessElement(this);
class StatelessElement extends ComponentElement {
/// 直接创建一个给定的widget元素,之后渲染到树上
StatelessElement(StatelessWidget widget) : super(widget);
}
State
的setstate()
方法确保状态在放改变时及时通知。StatefulWidget
和SatelessWidget
一样本事是不可以改变状态的,之所以可以改变状态,是因为此类内部内置一个State
订阅对象,而State
对象是有生命周期的,并与widget绑定,来更改widget的状态。StatefulWidget:
abstract class StatefulWidget extends Widget {
const StatefulWidget({ Key key }) : super(key: key);
/// Creates a [StatefulElement] to manage this widget's location in the tree.
///系统调用。创建一个有状态元素来管理这个这个widget在widget树中的位置
@override
StatefulElement createElement() => StatefulElement(this);
@protected
State createState();
}
StatefulElement(this);
class StatefulElement extends ComponentElement {
/// Creates an element that uses the given widget as its configuration.
StatefulElement(StatefulWidget widget)
//此时会创建一个State对象来和widget绑定,通过State的生命周期来监听widget的状态
: _state = widget.createState(), super(widget) {..各种断言..}
@override
Widget build() => state.build(this);
/// The [State] instance associated with this location in the tree.
/// 与树中此位置的widget关联,一一对应
State<StatefulWidget> get state => _state;
State<StatefulWidget> _state;
.....
}
它封装了许多应用程序通常需要的小部件,并添加了特定的设计功能,如主题,网格像素。
为了继承主题数据,widget需要位于MaterialApp
内才能正常显示,通常使用MaterialApp
来运行应用。
参数home
、routes
、onGenerateRoute
或builder
中至少一个是非空的,这里指定的路由是应用程序启动的路由。
如果只指定routes
参数,那么集合中必须含有一个key为:Navigator.defaultRouteName
或'/'
的路由,因为这俩key表示程序启动的路由根路径。
home
的路由路径为:'/'
,等价于Navigator.defaultRouteName
。
所以home
参数和routes
参数内key为的Navigator.defaultRouteName
或'/'
的路由不能同时出现,否则会冲突。
字段 | 类型 | 作用 | |
---|---|---|---|
1 | navigatorKey | Globalkey | 导航键,全局唯一 |
2 | home | widget | 主页 |
3 | routes | Map |
路由表,内含各种widget |
4 | initialRoute | String | 初始路由 |
5 | onGenerateRoute | RouteFactory | 生成路由,当初始路由未找到时,展示此页面 |
6 | onUnknownRoute | RouteFactory | 未知路由 |
7 | navigatorObservers | List | 导航监听器 |
8 | builder | TransitionBuilder | widget的构建者 |
9 | title | String | 任务管理器中应用程序标题 |
10 | onGenerateTitle | GenerateAppTitle | 生成标题,每次在WidgetsApp构建时都会重新生成 |
11 | color | Color | 任务管理器中应用程序title颜色 |
12 | theme | ThemeData | 主题 |
13 | locale | Locale | app语言支持 |
14 | localizationsDelegates | Iterable |
多语言代理 |
15 | localeResolutionCallback | LocaleResolutionCallback | 区域分辨回调 |
16 | supportedLocales | Iterable | 支持的多语言 |
17 | debugShowMaterialGrid | bool | 调试显示材质网格,默认false |
18 | showPerformanceOverlay | bool | 打开性能监控,覆盖在屏幕最上面,默认false |
19 | checkerboardRasterCacheImages | bool | 打开栅格缓存图像的检查板。默认false |
20 | checkerboardOffscreenLayers | bool | 打开显示到屏幕外位图的图层的检查面板。默认false |
21 | showSemanticsDebugger | bool | 打开一个覆盖图,显示框架报告的可访问性信息,显示边框,默认false |
22 | debugShowCheckedModeBanner | bool | 右上角显示一个debug的图标,默认为true |
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
//默认设置
debugShowMaterialGrid: false,//17
showPerformanceOverlay: false,//18
checkerboardRasterCacheImages: false,//19
checkerboardOffscreenLayers: false,//20
showSemanticsDebugger: false,//21
debugShowCheckedModeBanner: true,//22
);
}
home
、routes
、initialRoute
、onGenerateRoute
、onUnknownRoute
和builder
:
builder
:
home
的作用一样,首次打开的路由,但优先级最高,不能为null。builder
设置后,initialRoute
设置也失效,即启动后只显示builder设置的路由界面。使用:
new MaterialApp(
builder: (BuildContext context, Widget child) {
return new BuilderPage();//这是页面
},
)
home
:主页,
'/'
,默认首先打开此路径的路由。routes
:路由集合
Navigator.pushNamed(context, '/TwoPage');
调用。Navigator.pushNamed
推送命名路由的时候,会在routes
中查找路由名字,然后使用对应的 WidgetBuilder 来构造一个带有页面切换动画的MaterialPageRoute。routes
不存在,则会通过onGenerateRoute
来查找。home
不为null,routes
中不能包含key为Navigator.defaultRouteName
或'/'
的路由,否则会冲突。使用:
new MaterialApp(
routes: {
///这两个不能同时出现,而且home不为null,不可以设置这个
//'/': (BuildContext context) => new OnePage(),
//Navigator.defaultRouteName:(BuildContext context) => new MyHomePage(),
//key:value形式
'/TwoPage': (BuildContext context) => new TwoPage(),
},
)
initialRoute
:初始路由
routes
集合中查找路由。home
或routes
中设置的Navigator.defaultRouteName
(或'/'
)路由,也会打开,并被此路由覆盖,点击返回可以推到home
路由 (home还是位于一级) 。使用:
new MaterialApp(
routes: {
///这两个不能同时出现,而且home不为null,不可以设置这个
// '/': (BuildContext context) => new OnePage(),
// Navigator.defaultRouteName:(BuildContext context) => new MyHomePage(),
//key:value形式
'/TwoPage': (BuildContext context) => new TwoPage(),
},
initialRoute: '/TwoPage',
)
onGenerateRoute
:生成路由
routes
中没有查找命名路由时,则会先调用此路由。home
为null,并且routes
中也没有设置根路由Navigator.defaultRouteName
或'/'
时,则会将此路由设置的'/'
路径下,并打开此路由。initialRoute
被设置,但未被找到时,也会回调此路由;使用:
如果 1.未定义'/'
路径下路由 和 2.设置initialRoute
的路由但未被找到,此时都将回调onGenerateRoute
的路由,此时将打开两次onGenerateRoute
的路由。
new MaterialApp(
//未设置'/'路径下的路由
routes: {
'/TwoPage': (BuildContext context) => new TwoPage(),
},
//此处的路由未定义,所以不会被找到
initialRoute: '/TwoPage1',
//设置了此路由,
onGenerateRoute: (RouteSettings setting) {
return MaterialPageRoute(//此处返回一个`Route`类型的路由,系统提供了几个实现类
builder: (BuildContext context) {
return GeneratePage();
},
);
},
)
onUnknownRoute
:未知路由
当前几项设置均为找到时,则会回调此路由。
title
、onGenerateTitle
、color
title
:任务管理界面,显示的APP的标题,不同手机效果不同。onGenerateTitle
:当与title
同时设置时,此参数生效。color
:任务管理界面,APP的图标颜色。NavigatorObserver
接口的监听器。Navigator.of(context).pop();
关闭当前路由。NavigatorObserver接口有如下函数:
class NavigatorObserver {
/// 进入路由
void didPush(Route<dynamic> route, Route<dynamic> previousRoute) { }
/// 弹出路由
void didPop(Route<dynamic> route, Route<dynamic> previousRoute) { }
///删除路由
void didRemove(Route<dynamic> route, Route<dynamic> previousRoute) { }
/// 用新路由替换旧路由
void didReplace({ Route<dynamic> newRoute, Route<dynamic> oldRoute }) { }
/// 用户势控制路由
/// For example, this is called when an iOS back gesture starts, and is used
/// to disabled hero animations during such interactions.
void didStartUserGesture() { }
///用户手势不再控制路由,与上一个相配
void didStopUserGesture() { }
}
使用方式:
routes
集合统一管理,并注册导航监听器class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
//统一管理各个路由
routes: {
'/OnePage': (BuildContext context) => new OnePage(),
'/TwoPage': (BuildContext context) => new TwoPage(),
'/GeneratePage': (BuildContext context) => new GeneratePage(),
},
//注册路由监听器
navigatorObservers: [//这个监听器是个集合,可根据不同需求对路由做不同的设置
new MyNavigatorObserver(),
],
);
}
}
class MyHomePage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('MaterialApp'),
),
body:Center(//这是个将子widget放入中间位置的widget
child: RaisedButton(//这是一个按钮
child: Text('skip one page'),//按钮上文字
onPressed: () {//点击事件
//路由跳转,使用pushName方法可以获得路由名字,此字符串为routes内的key
Navigator.pushNamed(context, '/OnePage');
},
),
),
);
}
}
class OnePage extends StatelessWidget {
@override
Widget build(BuildContext context) => new OnePageFull();
}
class OnePageFul extends StatefulWidget {
@override
_OnePageFulState createState() => _OnePageFulState();
}
class _OnePageFulState extends State<OnePageFul> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('one page'),
),
body: Center(
child: RaisedButton(
child: Text('skip two page'),
onPressed: () {
//以命名的名字跳转的方法
Navigator.pushNamed(context, '/TwoPage');
///另一种方法,在two page跳转到generate page时使用的,如:
//Navigator.of(context).push(
// new MaterialPageRoute(
// builder: (BuildContext context) => new GeneratePage(),
// ),
//);
},
),
),
);
}
}
**导航监听器:**监听各个路由进入和弹出,如果路由没有放入routes
集合被命名,那么此路由的name为null。
class MyNavigatorObserver extends NavigatorObserver {
///route 当前路由
///previousRoute 先前活动的路由
///放入路由 即打开
@override
void didPush(Route route, Route previousRoute) {
print('----------push-----------');
print('当前活动的路由:${route.settings}');
print('先前活动的路由:${previousRoute?.settings}');
print('----------end-----------');
}
///弹出当前路由
@override
void didPop(Route route, Route previousRoute) {
print('----------pop-----------');
print('当前活动的路由:${route.settings}');
print('先前活动的路由:${previousRoute?.settings}');
print('----------end-----------');
}
}
//首次进入,首页路由
----------push-----------
当前活动的路由:"/"
先前活动的路由:null
----------end-----------
//跳转到one page路由
----------push-----------
当前活动的路由:"/OnePage"
先前活动的路由:"/"
----------end-----------
//跳转到two page路由
----------push-----------
当前活动的路由:"/TwoPage"
先前活动的路由:"/OnePage"
----------end-----------
//跳转到generate page路由,此处路由未被命名,打印name为null
----------push-----------
当前活动的路由:"null"
先前活动的路由:"/TwoPage"
----------end-----------
//从generate page返回上一个路由two page
----------pop-----------
当前弹出的路由:"null"
先前活动的路由:"/TwoPage"
----------end-----------
//从two page返回上一个路由one page
----------pop-----------
当前弹出的路由:"/TwoPage"
先前活动的路由:"/OnePage"
----------end-----------
//从one page返回上一个home路由
----------pop-----------
当前弹出的路由:"/OnePage"
先前活动的路由:"/"
----------end-----------
ThemeDate
,提供了几种工厂构造方法如下:factory ThemeData({
//..各种选填参数,一共45个..
//未设置会有默认值,然后将值付给raw构造
return ThemeData.raw(..各种必填非null参数..);
})
//常量构造方式,内部参数必不为null,而且必填
const ThemeData.raw({..各种必填非null参数..})
///一个默认淡蓝色主题
factory ThemeData.light() => ThemeData(brightness: Brightness.light);
///一个默认的黑色主题,带有蓝绿色调。
factory ThemeData.dark() => ThemeData(brightness: Brightness.dark);
//默认为淡蓝色主题:
factory ThemeData.fallback() => ThemeData.light();
///创建此主题的副本,但使用新值替换给定字段。
ThemeData copyWith({
//...
return ThemeData.raw(..各种必填非null参数..);
})
///将带有[baseTheme]基础主题和[localTextGeometry]文本主题合并生成的新主题,。
static ThemeData localize(ThemeData baseTheme, TextTheme localTextGeometry){}
///两个主题之间的线性插值。t取值为0.0到1.0,将两个主题的颜色从0.0到1.0调节
static ThemeData lerp(ThemeData a, ThemeData b, double t){}
参数描述:
太多了自己试吧!看着都头疼,大部分时候使用默认的,自定义时也只是很少的主体颜色。
名称 | 类型 | 作用 |
---|---|---|
brightness | Brightness | 描述整体主题的调度,包括按钮,画布,卡片和原色的亮度;默认为light。 |
primarySwatch | MaterialColor | 原色样本,供primaryColor使用;默认设置blue。 |
primaryColor | Color | 状态栏和标题栏bars的背景颜色;默认为primarySwatch的值。 |
primaryColorBrightness | Brightness | 状态栏和bars的亮度;默认根据背景颜色的阙值来设置light 或dark。 |
primaryColorLight | Color | 状态栏和bars颜色的较浅版本。 |
primaryColorDark | Color | 状态栏和bars颜色的较深版本。 |
accentColor | Color | 小部件的前景色(旋钮、文本、覆盖边缘效果等)。默认根据不同主题亮度显示不同。 |
accentColorBrightness | Brightness | 小部件的前景色亮度,用于确定文本的颜色和放在强调颜色之上的图标(如浮动按钮);默认根据颜色阙值设置。 |
canvasColor | Color | 画布颜色,即页面颜色;默认根据亮度设置 |
scaffoldBackgroundColor | Color | 应用程序内页面的背景颜色;默认为canvasColor颜色 |
bottomAppBarColor | Color | 底部bar的背景颜色;默认根据亮度设置,亮时为白色。 |
cardColor | Color | 使用卡片组件时,卡片的背景颜色;默认根据亮度设置,亮时为白色。 |
dividerColor | Color | 分割线的颜色,如Divider 、PopupMenuDivider 、ListTile 和 DataTable 之间的分割线。 |
highlightColor | Color | 选中后的颜色。 |
splashColor | Color | 触摸,点击后的颜色 |
splashFactory | InteractiveInkFeatureFactory | 定义触摸点击后的动画效果,类似水波纹。 |
selectedRowColor | Color | 用于突出显示选定行的颜色。 |
unselectedWidgetColor | Color | 用于处于非活动(但已启用)状态的小部件的颜色。如,未选中的复选框。通常与accentColor形成对比。 |
disabledColor | Color | 用于无效部件的颜色,无论其状态是如何 |
buttonColor | Color | 按钮的背景颜色;默认根据亮度设置。 |
buttonTheme | ButtonThemeData | 按钮的主题。包括背景颜色大小和文本主题 |
secondaryHeaderColor | Color | 未知 |
textSelectionColor | Color | 选中文本的颜色 |
cursorColor | Color | 文本输入框光标颜色 |
textSelectionHandleColor | Color | 调整当前选定的文本部分的句柄的颜色。光标下的句柄。 |
backgroundColor | Color | 与primaryColor形成对比,如进度条剩余部分颜色。 |
dialogBackgroundColor | Color | 对话框的背景颜色;默认根据亮度改变,light时为白色。 |
indicatorColor | Color | |
hintColor | Color | 文本或占位符文本的颜色,如输入框TextField失去焦点后的颜色。 |
errorColor | Color | 用于输入验证错误的颜色,例如在[TextField]字段中。 |
toggleableActiveColor | Color | 用于突出显示可切换小部件的活动状态的颜色,如[开关]、[收音机]和[复选框]。 |
fontFamily | String | 文本字体名称。 |
textTheme | TextTheme | 文本主题,与卡片和画布颜色形成对比。 |
primaryTextTheme | TextTheme | 文本主题,与primary颜色形成对比 |
accentTextTheme | TextTheme | 文本主题,与accent颜色形成对比 |
inputDecorationTheme | InputDecorationTheme | 输入框的主题 |
iconTheme | IconThemeData | 图标主题,与卡片和画布形成对比 |
primaryIconTheme | IconThemeData | 图标主题,与primary颜色形成对比。 |
accentIconTheme | IconThemeData | 图标主题,与accent颜色形成对比。 |
sliderTheme | SliderThemeData | [滑块]的颜色和形状的主题。这是从[SliderTheme.of]返回的值。 |
tabBarTheme | TabBarTheme | 自定义选项卡栏指示器的大小、形状和颜色的主题。 |
chipTheme | ChipThemeData | 渲染[Chip]所用的颜色和样式,这是从[ChipTheme.of]返回的值。 |
platform | TargetPlatform | 使小部件适应目标平台,默认为当前平台 |
materialTapTargetSize | MaterialTapTargetSize | 小部件的tap目标和布局的大小,默认为padded填充,48px*48px |
pageTransitionsTheme | PageTransitionsTheme |
这个widget部件是一个实现了基本布局结构布局。
它提供了一个应用程序结构包括:
appBar
:
AppBar()
;body
:
body
位置appBar
下,浮点按钮和drawer后。drawer
:
Drawer
。endDrawer
:
floatingActionButton
:
body
上面;通常使用api类FloatingActionButton
;body
的右下角。floatingActionButtonLocation
:
FloatingActionButtonLocation.endFloat
;body
右下角。floatingActionButtonAnimator
:
FloatingActionButtonAnimator.scaling
;FloatingActionButtonAnimator
,其中提供几种实现动画。persistentFooterButtons
:
FlatButton
部件,;body
下,bottomNavigationBar
之上,始终可见,不随body
滚动。bottomNavigationBar
:
SnackBar
从之上滑出。bottomSheet
:
body
下,bottomNavigationBar
和persistentFooterButtons
之上;SnackBar
出现位置相同,同时出现会覆盖SnackBar
backgroundColor
:
resizeToAvoidBottomPadding
:
body
是否自行调整大小,避免窗口的底部填充;默认为true。primary
:
appBar
高度将+状态栏高度;AppBar.primary
为true;Scaffold(
appBar: AppBar(
title: Text('This is appBar'),
),
body: Container(
width: 1600.0,
color: Colors.yellow,
child: ListView(
children: <Widget>[
Container(
width: 160.0,
alignment: Alignment.center,
child: RaisedButton(
child: Text('skip two page'),
onPressed: () {},
),
),
Container(
height: 250.0,
alignment: Alignment.center,
child: Text(
'This is body',
style: TextStyle(fontSize: 20.0),
),
),
],
),
),
//左边的抽屉,设置后AppBar左边会有个图标按钮
drawer: new Drawer(
child: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.change_history),
title: Text('Change history'),
onTap: () {
Navigator.pop(context); // close the drawer
},
),
//..三个....
],
),
),
//右边的抽屉,设置后AppBar右边会有个图标按钮
endDrawer: new Drawer(
child: ListView(
children: <Widget>[
ListTile(
leading: Icon(Icons.change_history),
title: Text('Change history'),
onTap: () {
Navigator.pop(context); // close the drawer
},
),
//..三个....
],
),
),
floatingActionButton: new Builder(
builder: (BuildContext context) {
return new FloatingActionButton(
onPressed:null,
child: new Icon(Icons.add),
);
},
),
bottomNavigationBar: BottomAppBar(
child: Container(
alignment: Alignment.center,
height: 50.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text('this'),
Text('is'),
Text('bottomNavigationBar'),
],
),
),
),
persistentFooterButtons: <Widget>[
new FlatButton(
onPressed: () {},
child: new Text('This'),
),
new FlatButton(
onPressed: () {},
child: new Text('is'),
),
new FlatButton(
onPressed: () {},
child: new Text('persistentFooterButtons'),
),
],
bottomSheet: Container(
color: Colors.cyanAccent,
height: 50.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Text('This'),
Text('is'),
Text('bottomSheet'),
],
),
),
);
}
名字 | 类型 | 作用 |
---|---|---|
leading | widget | 标题前的widget小部件,默认为null。此时可根据下一个参数控制。 |
automaticallyImplyLeading | bool | 控制Leading的,默认为true。当为true和leading为null时,将自动推断leading部件是什么;如果为false和leading为null时,则留出title前导空间。如果leading不为空,则此设置失效。 |
title | widget | 标题部件。通常为Text描述界面内容。 |
actions | List | 标题后面的小部件组。通常使用IconButton。 |
flexibleSpace | widget | 一个灵活的小部件,堆叠在toolbar和tabbar后面。它的高度将与appBar的总高度相同。只有在AppBar高度改变时才会有灵活的表现。 |
bottom | PreferredSizeWidget | appBar底部的部件,通常使用TabBar |
elevation | double | appBar底部阴影大小,默认为4.0,。 |
backgroundColor | Color | 背景颜色,通常与[brightness]、[iconTheme]、[textTheme]一起设置 |
brightness | Brightness | 亮度 |
iconTheme | IconThemeData | 图标的主题 |
textTheme | TextTheme | 文本主题 |
primary | bool | appBar是否现在在屏幕顶部,默认为true。appBar的高将加上状态栏的高度。 |
centerTitle | bool | 标题是否居中 |
titleSpacing | double | 标题四周间距 |
toolbarOpacity | double | appBar的透明度,取值0.0-1.0,默认为1.0. |
bottomOpacity | double | appBar底部的透明度,默认为1.0. |
new AppBar(
leading: Icon(Icons.arrow_back),
automaticallyImplyLeading: true,
title: Container(
color: Colors.yellow,
child: Text(
'title',
style: TextStyle(color: Colors.red),
),
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.flag),
onPressed:null,
),
IconButton(
icon: Icon(Icons.access_alarm),
onPressed:null,
),
],
flexibleSpace: Container(
color: Colors.purpleAccent,
child: FlexibleSpaceBar(
centerTitle: true,
title: Container(
color: Colors.redAccent,
child: Text('flexibleSpace'),
),
),
),
elevation: 14.0,
centerTitle: true,
)
State
类中;Element
,而Element
就负责状态和生命周期的管理;StatefulWidget
通过createElement()
创建StatefulElement
,StatefulElement
内部会负责创建和保存 State
,这就是为什么StatefulWidget
被重新创建而内部的状态不会丢失的原因;源码见上面widget。RenderObject
:负责视图渲染。所有的布局、绘制和事件响应全都由它负责。initState()
:
BuildContext.inheritFromWidgetOfExactType
;super.iniState()
后didChangeDependencies()
:
initState()
后面调用;build
的调用引用了后来更改的InheritedWidget
,那么框架将调用这个方法来通知这个对象更改的消息;build
;BuildContext.inheritFromWidgetOfExactType
。build(BuildContext context)
:
initState()
后;didUpdateWidget()
后;setState()
之后;State
对象的依赖更改之后(如:前面build
更改引用的InheritedWidget
);deactivate()
后,再将State
对象重新插入到渲染树的另一个位置。didUpdateWidget(LifecyclePageFull oldWidget)
:
super.didUpdateWidget(oldWidget)
之后。deactivate()
:
dispose()
之前调用。super.deactivate()
之前;dispose()
:
setState()
是错误的;super.dispose()
之前;AppLifecycleState
提供四种状态:
resumed
:
inactive
:
paused
状态paused:
Window.onBeginFrame
和Window.onDrawFrame
。suspending
Window.onBeginFrame
和Window.onDrawFrame
。class _LifecyclePageFullState extends State<LifecyclePageFull>
with WidgetsBindingObserver {
int number = 0;
@override
void initState() {
print('生命周期--initState');
super.initState();
//注册widget监听,复写时要在super之后
WidgetsBinding.instance.addObserver(this);
}
@override
void didChangeDependencies() {
print('生命周期--didChangeDependencies');
super.didChangeDependencies();
}
@override
void didUpdateWidget(LifecyclePageFull oldWidget) {
print('生命周期--didUpdateWidget');
super.didUpdateWidget(oldWidget);
}
@override
void deactivate() {
print('生命周期--deactivate');
super.deactivate();
}
@override
void dispose() {
print('生命周期--dispose');
//注销widget监听,复写时要在super之前
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.inactive:
print('Observer--可见没有响应inactive');
break;
case AppLifecycleState.paused:
print('Observer--不可见不响应paused');
break;
case AppLifecycleState.resumed:
print('Observer--可见可交互resumed');
break;
case AppLifecycleState.suspending:
print('Observer--申请暂停suspending');
break;
}
super.didChangeAppLifecycleState(state);
}
@override
Widget build(BuildContext context) {
print('生命周期--build');
return new Scaffold(
appBar: new AppBar(
centerTitle: true,
title: new Text('leftcycle'),
),
body: new Center(
child: new Text(
'$number',
style: TextStyle(fontSize: 25.0),
),
),
floatingActionButton: new FloatingActionButton(
onPressed: () {
setState(() {
print('number加1了');
number++;
});
},
child: new Icon(Icons.add),
),
);
}
}
当界面从创建到可见时:
initState()
–>didChangeDependencies()
–>build()
打印结果:
//生命周期--initState
//生命周期--didChangeDependencies
//生命周期--build
当从渲染树删除时:点击返回键
deactivate()
–>dispose()
打印结果:
//生命周期--deactivate
//生命周期--dispose
横竖屏切换:
didUpdateWidget()
–>build()
,将调用两次(荣耀8)
打印结果:
//生命周期--didUpdateWidget
//生命周期--build
//生命周期--didUpdateWidget
//生命周期--build
点击home键:
AppLifecycleState.inactive
–>AppLifecycleState.paused
打印结果:
//Observer--可见没有响应inactive
//Observer--不可见不响应paused
从任务管理器唤起应用:
AppLifecycleState.inactive
–> AppLifecycleState.resumed
打印结果:
//Observer--可见没有响应inactive
//Observer--可见可交互resumed
点击浮点按钮:
调用build()
打印结果:
//number加1了
//生命周期--build