Flutter 小知识整理

520 阅读4分钟

StatelessWidget && StatefulWidget

StatelessWidget 不需要更改内部状态的组件

  • build方法被调用的场景
  1. 当StatelessWidget 被插入widget树中
  2. 当StatelessWidget的父级更改其配置时
  3. 当StatelessWidget依赖的InheritedWidget发生变化时

StatefulWidget 组件是需要进行变化的

  • 使用setState()管理StatefulWidget的状态的改变。(类似于ReactsetState())
  • setState()方法会告诉flutter框架某个状态发生了变化,然后调用该组件的 build() ,重新渲染

总结

  • 有状态还是无状态取决于组件是否有状态改变
  • 如果需要用户交互或者数据改变导致widget改变,那么它就是有状态的
  • 如果一个widget是最终的或者不可变的,那么它就是无状态的

生命周期

  • 简介: 类似于iOS的viewcontroller的生命周期,StatelessWidget和StatefulWiget的生命周期是不一样的

  • 本质:

  1. 回调方法(函数)。
  2. 让开发者知道当前widget处于什么样的状态
  • 作用:
  1. 监听widget的事件
  2. 初始化数据(创建数据、发送网络请求...)
  3. 内存管理(销毁数据、移除监听、销毁timer...)
  • 大体阶段
  1. 初始化(插入渲染树)
  2. 状态改变(在渲染树中存在)
  3. 销毁(从渲染树种移除)

StatelessWidget 生命周期函数

基本顺序函数
1StatelessWidget-构造函数
2StatelessWidget-build()

StatefulWidget 生命周期函数

图片来自 blog.csdn.net/u011272795/…

基本顺序函数细节调用次数是否支持setState
1StatefulWidget-构造方法1
2StatefulWidget-State-构造方法1
3StatefulWidget-State-initState()1
4StatefulWidget-State-didChangeDependencies()1.initState() 之后调用会调用一次
2.当依赖的InheritedWidget发生变化时,也会调用,并且低调用多次
>=1
5StatefulWidget-State-build()>=1
6StatefulWidget-State-deactivate()>=1
7StatefulWidget-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:

  1. State 的类 mix WidgetsBindingObserver
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
    ...
}
  1. 在 State 的 initState 里添加监听:
@override
  void initState(){
    super.initState();
    WidgetsBinding.instance.addObserver(this);
}
  1. 在 State 的 dispose 里移除监听:
  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    WidgetsBinding.instance.removeObserver(this);
  }
  1. 在 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…