flutter學習日記(三)————Flutter的生命週期和路由

XiaoCheng123發表於2019-12-18

Flutter的生命週期

Flutter主要有兩種:無狀態的 StatelessWidget和有狀態的 StatefulWidget

1. StatelessWidget

一個 StatelessWidget 是不能被改變的,比如:Icon、Text等。由於不可改變,因此並沒有什麼生命週期。

2. StatefulWidget

一個 StatefulWidget 是有狀態的,可變的。一個 StatefulWidget 元件可以通過定義它的 State 來進行對元件資料狀態的儲存和修改。那麼它的State應該是有一系列的生命週期。

image

上圖就是 State 的生命週期圖。

  1. StatefulWidget.createState()Framework 呼叫會通過呼叫 StatefulWidget.createState() 來建立一個 State。

  2. initState()新建立的 State 會和一個 BuildContext 產生關聯,此時認為 State 已經被安裝好了,initState() 函式將會被呼叫。通常,我們可以重寫這個函式,進行初始化操作。

  3. didChangeDependencies()在 initState() 呼叫結束後,這個函式會被呼叫。事實上,當 State 物件的依賴關係發生變化時,這個函式總會被 Framework 呼叫。

  4. build()經過以上步驟,系統認為一個 State 已經準備好了,就會呼叫 build() 來構建檢視。我們需要在這個函式中,返回一個 Widget。

  5. deactivate()當 State 被暫時從檢視樹中移除時,會呼叫這個函式。頁面切換時,也會呼叫它,因為此時 State 在檢視樹中的位置發生了變化,需要先暫時移除後新增。

    ⚠️注意,重寫的時候必須要呼叫 super.deactivate()。

  6. dispose()當 State 被永久的從檢視樹中移除,Framework 會呼叫該函式。在銷燬前觸發,我們可以在這裡進行最終的資源釋放。在呼叫這個函式之前,總會先呼叫 deactivate()。

    ⚠️注意,重寫的時候必須要呼叫 super.dispose()。

  7. didUpdateWidget(covariant T oldWidget)當 widget 的配置發生變化時,會呼叫這個函式。比如,Hot-reload 的時候就會呼叫這個函式。這個函式呼叫後,會呼叫 build()。

  8. setState()當我需要更新 State 的檢視時,需要手動呼叫這個函式,它會觸發 build() 。

Flutter的路由

Flutter裡面的路由主要是通過Navigator這個類進行控制的,當你想從這個頁面跳到另外一個頁面的時候,通過Navigator即可 ⚠️呼叫的時候要注意頁面是入棧操作,千萬別累積了太多的頁面

這裡為了更加直觀的展示路由之間的跳轉和轉換,我將我專案裡面封裝的一個NavigatorUtils的程式碼展現出來

import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_xinqiu/page/home_page.dart';
import 'package:flutter_xinqiu/page/login_page.dart';
import 'package:flutter_xinqiu/page/noob_setting_page.dart';
import 'package:flutter_xinqiu/page/user_idea_page.dart';
import 'package:flutter_xinqiu/widget/custom_route.dart';

/**
 * 路由跳轉
 * Created by xiaocheng123
 * Date: 2019-7-8
 */
class NavigatorUtils {
  ///替換
  static pushReplacementNamed(BuildContext context, String routeName) {
    Navigator.pushReplacementNamed(context, routeName);
  }

  ///切換無引數頁面
  static pushNamed(BuildContext context, String routeName) {
    Navigator.pushNamed(context, routeName);
  }

  ///主頁
  static goHome(BuildContext context) {
    Navigator.pushReplacementNamed(context, HomePage.sName);
  }

  ///登入頁
  static goLogin(BuildContext context) {
    // Navigator.pushReplacementNamed(context, LoginPage.sName);
    Navigator.of(context).pushAndRemoveUntil(
    new MaterialPageRoute(builder: (context) => new LoginPage()
    ), (route) => route == null);
  }

  ///新手設定頁面
  static goNoobSetting(BuildContext context) {
    Navigator.of(context).push(CustomRoute(NoobSettingPage()));
  }

  ///意見反饋設定頁面
  static goUserIdea(BuildContext context) {
    Navigator.push(context,
        new CupertinoPageRoute(builder: (context) => pageContainer(UserIdeaPage())));
  }

  ///公共開啟方式
  static NavigatorRouter(BuildContext context, Widget widget) {
    return Navigator.push(context,
        new CupertinoPageRoute(builder: (context) => pageContainer(widget)));
  }

  ///Page頁面的容器,做一次通用自定義
  static Widget pageContainer(widget) {
    return MediaQuery(

        ///不受系統字型縮放影響
        data: MediaQueryData.fromWindow(WidgetsBinding.instance.window)
            .copyWith(textScaleFactor: 1),
        child: widget);
  }
}

複製程式碼

在程式碼裡面可以將跳轉到某個路由進行封裝起來,這樣進行路由跳轉的時候直接引用即可

相關文章