Flutter的一輩子

說明: 本篇文章已受權微信公衆號 Flutter那些事 獨家發佈,未經受權,嚴禁轉載!java

1. 前言 在初學新技術以前,咱們總會要從最基本的東西瞭解起來,就比如當接觸Android的時候,咱們學四大組件都要學很久,是否還記得在Android的生命週期?首先讓咱們回顧下Android中的生命週期 bash

Android生命週期
關於這個就不在多說了,經常使用場景總結下:

1.啓動Activity:系統會先調用onCreate方法,而後調用onStart方法,最後調用onResume,Activity進入運行狀態。

2.當前Activity被其餘Activity覆蓋其上或被鎖屏:系統會調用onPause方法,暫停當前Activity的執行。

3.當前Activity由被覆蓋狀態回到前臺或解鎖屏:系統會調用onResume方法,再次進入運行狀態。

4.當前Activity轉到新的Activity界面或按Home鍵回到主屏,自身退居後臺:系統會先調用onPause方法,而後調用onStop方法,進入停滯狀態。

5.用戶後退回到此Activity:系統會先調用onRestart方法,而後調用onStart方法,最後調用onResume方法,再次進入運行狀態。

6.當前Activity處於被覆蓋狀態或者後臺不可見狀態,即第2步和第4步,系統內存不足,殺死當前Activity,然後用戶退回當前Activity:再次調用onCreate方法、onStart方法、onResume方法,進入運行狀態。

7.用戶退出當前Activity:系統先調用onPause方法,而後調用onStop方法,最後調用onDestory方法,結束當前Activity。
複製代碼

emmm,相信小夥伴們如今應該記憶起來了吧,前戲好了,進入主題,聊聊咱們今天的主人公"State"微信

2. Widget概念 在咱們的主人公出場前,先認識下他的小夥伴網絡

Flutter中幾乎全部的對象都是一個Widget,與原生開發中「控件」不一樣的是,
Flutter中的widget的概念更普遍,它不只能夠表示UI元素,也能夠表示一些功能性的組件如:用於手勢檢測的 GestureDetector widget、用於應用主題數據傳遞的Theme等等。
而原生開發中的控件一般只是指UI元素
複製代碼

3. State的引入app

  • StatelessWidget(用於不須要維護狀態的場景)
abstract class StatelessWidget extends Widget 複製代碼
  • StatefulWidget(用於須要維護狀態的場景)
abstract class StatefulWidget extends Widget 複製代碼

從上述的代碼中咱們看到他們都繼承了一個東西Widget,那就先簡單的看下這個類less

@immutable
abstract class Widget extends DiagnosticableTree {
  const Widget({ this.key });
  final Key key;

  @protected
  Element createElement();

  @override
  String toStringShort() {
    return key == null ? '$runtimeType' : '$runtimeType-$key';
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.defaultDiagnosticsTreeStyle = DiagnosticsTreeStyle.dense;
  }

  static bool canUpdate(Widget oldWidget, Widget newWidget) {
    return oldWidget.runtimeType == newWidget.runtimeType
        && oldWidget.key == newWidget.key;
  }
}
複製代碼

上述代碼中有一個咱們很常見的方法,每次在繼承的時候都須要重寫的一個方法ide

@override
  StatefulElement createElement() => StatefulElement(this);
複製代碼

繼續跟蹤StatefulElement發現存在一個*widget.createState()*方法,發現了就要繼續,寧殺錯,莫放過函數

class StatefulElement extends ComponentElement {
  /// Creates an element that uses the given widget as its configuration.
  StatefulElement(StatefulWidget widget)
      : _state = widget.createState(),
        super(widget) {
   .....
    assert(_state._element == null);
    _state._element = this;
    assert(_state._widget == null);
    _state._widget = widget;
    assert(_state._debugLifecycleState == _StateLifecycle.created);
  }

複製代碼

點擊createState方法咱們終於找到了今天的主人公,沒錯,就是它,State,跑不掉了。測試

@protected
  State createState();
複製代碼
  1. 生命週期 到了如今這一步,咱們已經找到想要的了,正如前面所說,Android有本身的生命週期,那麼做爲Flutter也有本身獨特的生命週期
    Flutter生命週期
    嗯,我一眼就看到了initState這個方法,還記得在網絡請求的時候亦或是變量的初始化,老是要寫到這個方法裏面
@override
 void initState() {
   // TODO: implement initState
   super.initState();
   _loadItemPage();
 }
複製代碼

咱們能夠將上述方法分爲三個部分進行描述,見下圖: ui

在這裏插入圖片描述
大體能夠當作三個階段

  • 初始化(插入渲染樹)
  • 構造函數
不屬於生命週期,由於這個時候State的widget屬性爲空,此時沒法在構造函數中訪問widget屬性
複製代碼
  • initState
/// Called when this object is inserted into the tree.
  
這個函數在生命週期中只調用一次。這裏能夠作一些初始化工做,好比初始化State的變量
複製代碼
  • didChangeDependencies
/// Called when a dependency of this [State] object changes.
 
這個函數會緊跟在initState以後調用
複製代碼
  • 狀態改變(在渲染樹中存在)
  • didUpdateWidget
/// Called whenever the widget configuration changes.
 
當組件的狀態改變的時候就會調用didUpdateWidget,好比調用了setStat
複製代碼
  • 銷燬(從渲染樹種移除)
  • deactivate
/// Called when this object is removed from the tree.
 
在dispose以前,會調用這個函數。
複製代碼
  • dispose
/// Called when this object is removed from the tree permanently.
 
一旦到這個階段,組件就要被銷燬了,這個函數通常會移除監聽,清理環境。
複製代碼

這個函數在生命週期中只調用一次。這裏能夠作一些初始化工做,好比初始化State的變量。

大致這樣吧,最後來個圖表總結下

階段 調用次數 是否支持setState
構造函數 1
initState 1 支持但無效(使用setState和不使用同樣)
didChangeDependencies >=1 支持但無效
didUpdateWidget >=1 支持但無效
deactivate >=1
dispose 1
  1. 示例分析 可能有人會說,bb了那麼久,毛都沒看到一根,因此講了這麼多,不來點實際的怎麼對的住以前的bb呢?來人啊,上代碼
import 'package:flutter/material.dart';

class LifeState extends StatefulWidget {
  @override
  _lifeStates createState() => _lifeStates();
}

class _lifeStates extends State<LifeState> {
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print('initState');
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    print(state.toString());
  }

  @override
  void didChangeDependencies() {
    // TODO: implement didChangeDependencies
    super.didChangeDependencies();
    print('didChangeDependencies');
  }

  @override
  void didUpdateWidget(LifeState oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('didUpdateWidget');
  }

  @override
  Widget build(BuildContext context) {
    print('build');
    // TODO: implement build
    return MaterialApp(
      home: Center(
          child: GestureDetector(
        child: new Text('lifeCycle'),
        onTap: () {
          Navigator.of(context)
              .push(new MaterialPageRoute(builder: (BuildContext c) {
            return new Text('sdfs');
          }));
        },
      )),
    );
  }

  @override
  void reassemble() {
    // TODO: implement reassemble
    super.reassemble();
    print('reassemble');
  }

  @override
  void deactivate() {
    // TODO: implement deactivate
    super.deactivate();
    print('deactivate');
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    print('dispose');
  }
}

複製代碼

測試結果

  1. 建立widget
initState
didChangeDependencies
build
複製代碼
  1. 退出頁面
deactivate
dispose
複製代碼
  1. 點擊熱加載按鈕
reassemble
didUpdateWidget
build
複製代碼
  1. app從顯示到後臺(home鍵)
AppLifecycleState.inactive
AppLifecycleState.paused
複製代碼
  1. app從後臺回到前臺
AppLifecycleState.inactive
AppLifecycleState.resumed
複製代碼
相關文章
相關標籤/搜索