StatelessWidget && StatefulWidget
StatelessWidget 不需要更改内部状态的组件
- build方法被调用的场景
- 当StatelessWidget 被插入widget树中
- 当StatelessWidget的父级更改其配置时
- 当StatelessWidget依赖的
InheritedWidget
发生变化时
StatefulWidget 组件是需要进行变化的
- 使用
setState()
管理StatefulWidget
的状态的改变。(类似于React
中setState()
) setState()
方法会告诉flutter
框架某个状态发生了变化,然后调用该组件的build()
,重新渲染
总结
- 有状态还是无状态取决于组件是否有状态改变
- 如果需要用户交互或者数据改变导致widget改变,那么它就是有状态的
- 如果一个widget是最终的或者不可变的,那么它就是无状态的
生命周期
-
简介: 类似于iOS的viewcontroller的生命周期,StatelessWidget和StatefulWiget的生命周期是不一样的
-
本质:
- 回调方法(函数)。
- 让开发者知道当前widget处于什么样的状态
- 作用:
- 监听widget的事件
- 初始化数据(创建数据、发送网络请求...)
- 内存管理(销毁数据、移除监听、销毁timer...)
- 大体阶段
- 初始化(插入渲染树)
- 状态改变(在渲染树中存在)
- 销毁(从渲染树种移除)
StatelessWidget 生命周期函数
基本顺序 | 函数 |
---|---|
1 | StatelessWidget-构造函数 |
2 | StatelessWidget-build() |
StatefulWidget 生命周期函数
图片来自 blog.csdn.net/u011272795/…
基本顺序 | 函数 | 细节 | 调用次数 | 是否支持setState |
---|---|---|---|---|
1 | StatefulWidget-构造方法 | 1 | 否 | |
2 | StatefulWidget-State-构造方法 | 1 | 否 | |
3 | StatefulWidget-State-initState() | 1 | 否 | |
4 | StatefulWidget-State-didChangeDependencies() | 1.initState() 之后调用会调用一次 2.当依赖的InheritedWidget发生变化时,也会调用,并且低调用多次 | >=1 | 否 |
5 | StatefulWidget-State-build() | >=1 | 是 | |
6 | StatefulWidget-State-deactivate() | >=1 | 否 | |
7 | StatefulWidget-State-dispose() | 先调用deactivate()然后调用dispose() | 1 | 否 |
StatefulWidget-State-didUpdateWidget() | 在widget树中,父widget rebuild时,如果当前widget配置有变化,也会调用didUpdateWidget(),并且在调用之后,会调用build() | >=1 | 是 |
App的生命周期
flutter中APP的生命周期是AppLifecycleState
,是个枚举值:
enum AppLifecycleState {
//应用程序是可见的,并且响应用户输入
resumed,
/// 应用程序处于非活动状态,没有接收用户输入
/// On iOS
/// 在Android上,这对应于一个应用程序或Flutter主机视图运行在前台非活动状态
/// 当其他活动被关注时,应用程序会过渡到这种状态,比如分屏应用程序、电话呼叫、画中画应用程序、 /// 系统对话框或另一个窗口
///处于这种状态的应用程序应该假设它们可能在任何时候pause.
inactive,
/// 应用程序当前对用户不可见,不响应用户输入,并在后台运行。当应用程序处于这种状态时,引擎将不 ///会调用Window.onBeginFrame和Window.onDrawFrame回调。
paused,
///应用程序仍然驻留在Flutter引擎上,但是与任何主机视图分离。
///当应用程序处于这种状态时,引擎在没有视图的情况下运行。当引擎第一次初始化时,它可以处于 ///attaching a view 的过程中或在由于 Navigator pop,view被销毁之后。
detached,
}
可以用WidgetsBindingObserver 去监测,用法eg:
- State 的类 mix WidgetsBindingObserver
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
...
}
- 在 State 的 initState 里添加监听:
@override
void initState(){
super.initState();
WidgetsBinding.instance.addObserver(this);
}
- 在 State 的 dispose 里移除监听:
@override
void dispose() {
// TODO: implement dispose
super.dispose();
WidgetsBinding.instance.removeObserver(this);
}
- 在 State 里 override didChangeAppLifecycleState
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.paused) {
// went to Background
}
if (state == AppLifecycleState.resumed) {
// came back to Foreground
}
}
localStorage 本地数据持久化
shared_preferences --> 结构简单,少量
在少量、结构简单的情况下推荐使用 shared_preferences
。 它类似于React Native
中的AsyncStorage
。
- 简单的,
异步的
,持久化的key-value
存储系统; - 在
Android
上它是基于SharedPreferences
的; - 在
iOS
上它是基于NSUserDefaults
的
path_provider --> 文件
如果是一个较大的文件(视频、音乐...),推荐使用path_provider
。
- 以package的形式引入
- 在iOS类似于NSFileManager
- 提供获取路径(filePath:DocumentsDirectory/CacheDirectory..)及读写能力
- 异步的
Sqfite ---> 大量、复杂
在对于大量,复杂的数据时,推荐使用Sqfite
- 在Android,类似data/data/<package_name>/databases
- 在iOS,类似Documents directory
- 以package的形式引入
Application / Pulgin / Package / Module
- Application: 原生Flutter工程。标准的Flutter App工程,包含标准的Dart层与Native平台层
- Package: 纯Dart的通用组件。
- Pulgin: iOS和Android差异化。 包含Dart层与Native平台层的实现(Android或者iOS的底层封装),是一种特殊的
package
例如shared_preferences
在iOS和Android中的实现是不同的 - Module: 混合工程。flutter功能组件,
混编
到已有的安卓/iOS工程内
pub.dev/ 用于发布package
路由和导航
Navigator(栈) + Route(pages)
- 基本使用
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => Page2()));
Navigator.pop(context, result);
页面传值及回调
传值
Navigator.of(context).pushNamed(page3, arguments: "hi");
回调
onPressed: () async {
//navigationResult 就是回调
var navigationResult = await Navigator.push(
context, new MaterialPageRoute(builder: (context) => Page2()));
if (navigationResult == 'from_back') {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Navigation from back'),
));
} else if (navigationResult == 'from_button') {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Navigation from button'),
));
}
}
//pop传值
Navigator.pop(context, 'from_button');
优秀的第三方路由
- FlutterBoost 在现有应用程序中同时管理Native页面和Flutter页面,FlutterBoost帮你处理页面的映射和跳转
- Fluro
网络 dio
原生 http,三方 dio(封装http)
to do
juejin.cn/post/690536…