Flutter学习记录——14.生命周期

1.Flutter生命周期

我们先了解下生命周期的概念,也就是一个页面对象从创建到销毁的整个状态管理。我们看下 Flutter 的 State 生命周期的示意图:
生命周期

可以看到我们的一个页面在加载创建时需要执行:

构造函数 -> initState -> didChangeDependencies -> build 方法,然后才会渲染为一个页面。

当销毁关闭时:

deactivate -> dispose

内部的前后台页面状态变化主要有:

enum AppLifecycleState {
  // 恢复可见
  resumed,
  // 不可见,后台运行,无法处理用户响应
  inactive,
  // 处在并不活动状态,无法处理用户响应。例如来电,画中画,弹框
  paused,
  // 应用被立刻暂停挂起,ios上不会回调这个状态
  suspending,
}

当页面更新时会执行:

didUpdateWidget -> build

可能会调用多次。

那么接下来通过代码实例来了解 Flutter 的生命周期:

import 'package:flutter/material.dart';

class StateSamples extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return StateSamplesState();
  }
}

class StateSamplesState extends State<StateSamples>
    with WidgetsBindingObserver {
  //插入渲染树时调用,只调用一次
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }

  //构建Widget时调用
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('LifeCycleState'),
      ),
      body: Center(
        child: Column(
          children: <Widget>[],
        ),
      ),
    );
  }

  //state依赖的对象发生变化时调用
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  //组件状态改变时候调用,可能会调用多次
  @override
  void didUpdateWidget(StateSamples oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  //当移除渲染树的时候调用
  @override
  void deactivate() {
    super.deactivate();
  }

  //组件即将销毁时调用
  @override
  void dispose() {
    super.dispose();
    WidgetsBinding.instance.removeObserver(this);
  }

  //APP生命周期监听
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (state == AppLifecycleState.resumed) {
      //恢复可见
    } else if (state == AppLifecycleState.paused) {
      //处在并不活动状态,无法处理用户响应
      //例如来电,画中画,弹框
    } else if (state == AppLifecycleState.inactive) {
      //不可见,后台运行,无法处理用户响应
    } else if (state == AppLifecycleState.suspending) {
      //应用被立刻暂停挂起,ios上不会回调
    }
    super.didChangeAppLifecycleState(state);
  }

  //其他方法

  //热重载时调用
  @override
  void reassemble() {
    super.reassemble();
  }

  //路由弹出
  @override
  Future<bool> didPopRoute() {
    return super.didPopRoute();
  }

  //新的路由
  @override
  Future<bool> didPushRoute(String route) {
    return super.didPushRoute(route);
  }

  //系统窗口相关改变回调,例如旋转
  @override
  void didChangeMetrics() {
    super.didChangeMetrics();
  }

  //文字缩放大小变化
  @override
  void didChangeTextScaleFactor() {
    super.didChangeTextScaleFactor();
  }

  //本地化语言变化
  @override
  void didChangeLocales(List<Locale> locale) {
    super.didChangeLocales(locale);
  }

  //低内存回调
  @override
  void didHaveMemoryPressure() {
    super.didHaveMemoryPressure();
  }

  //当前系统改变了一些访问性活动的回调
  @override
  void didChangeAccessibilityFeatures() {
    super.didChangeAccessibilityFeatures();
  }

  //平台色调主题变化时
  @override
  void didChangePlatformBrightness() {
    super.didChangePlatformBrightness();
  }
}

2.Flutter按键监听

我们知道在 Android 或 iOS 平台上,手机上或遥控器上的一些实体按键是可以被监听到的,可以执行相关操作,当然 Flutter 上也可以进行按键监听。

首先看下返回键的监听,返回键监听拦截在 Flutter 中比较不一样。是单独使用一个组件:WillPopScope。

然后通过一个实例来看下 Flutter 中实现连按两次返回键退出的效果:

class KeyListenerState extends State<KeyListenerSamples> {
  int last = 0;
  int index = 0;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    // 要用WillPopScope包裹
    return WillPopScope(
      // 编写onWillPop逻辑
      onWillPop: _onWillPop,
      child: Scaffold(
          appBar: AppBar(
            title: Text('KeyListener Demo'),
          ),
          body: Center(
            child: Text("按键监听"),
          )),
    );
  }

  // 返回键拦截执行方法
  Future<bool> _onWillPop() {
    int now = DateTime.now().millisecondsSinceEpoch;
    print(now - last);
    if (now - last > 1000) {
      last = now;
      // showToast("再按一次返回键退出");
      return Future.value(false); //不退出
    } else {
      return Future.value(true); //退出
    }
  }
}

那么其他按键的监听使用的是 RawKeyboardListener。

RawKeyboardListener 继承自 StatefulWidget。

const RawKeyboardListener({
    Key key,
    // 焦点节点
    @required this.focusNode,
    // RawKeyEvent,按键事件
    @required this.onKey,
    // 子控件
    @required this.child,
  })

我们再看下 RawKeyEvent 的构造方法:

const RawKeyEvent({
    // RawKeyEventData
    @required this.data,
    this.character,
  })

监听 Android 平台使用 RawKeyEventDataAndroid,监听 Fuchsia 平台使用RawKeyEventDataFuchsia,iOS 平台暂时还没有发布。

RawKeyboardListener 用法:

class KeyListenerState extends State<KeyListenerSamples> {
  FocusNode focusNode = FocusNode();

  @override
  void initState() {
    super.initState();
    FocusScope.of(context).requestFocus(focusNode);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('RawKeyboardListener Demo'),
        ),
        // RawKeyboardListener包裹
        body: RawKeyboardListener(
            // 可以监听到的前提是有焦点,我们可以让组件先获取焦点
            focusNode: focusNode,
            onKey: (RawKeyEvent event) {
              // 这里是监听Android平台按键,并且是KeyDown事件
              if (event is RawKeyDownEvent &&
                  event.data is RawKeyEventDataAndroid) {
                RawKeyDownEvent rawKeyDownEvent = event;
                RawKeyEventDataAndroid rawKeyEventDataAndroid =
                    rawKeyDownEvent.data;
                print("keyCode: ${rawKeyEventDataAndroid.keyCode}");
                switch (rawKeyEventDataAndroid.keyCode) {
                  // 这里面的KeyCode值和Android平台的一致
                  case 19: //KEY_UP
                    break;
                  case 20: //KEY_DOWN
                    break;
                  case 21: //KEY_LEFT

                    break;
                  case 22: //KEY_RIGHT

                    break;
                  case 23: //KEY_CENTER
                    break;
                  default:
                    break;
                }
              }
            },
            child: Center(
              child: Text("按键监听"),
            )),
      );
  }
}

当然我们也可以把 RawKeyboardListener 应用在输入框的焦点获取和监听上。

3.总结

本节课主要是给大家讲解了 Flutter 的生命周期和按键监听的用法和特点。主要注意点和建议如下:

  • 重点掌握 Flutter 生命周期的几个状态和返回键的拦截处理的用法。
  • 尝试编写监听输入框的按键事件和焦点事件。
发布了253 篇原创文章 · 获赞 52 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_41151659/article/details/103392271