Flutter Widget and Bald

Flutter 是什麼?

咱們先來搬運官網的一段介紹,讓你們有一個直觀的認識:前端

Flutter是谷歌的移動UI框架,能夠快速在 iOS 和 Android 上構建高質量的原生用戶界面。
Flutter能夠與現有的代碼一塊兒工做。在全世界,Flutter正在被愈來愈多的開發者和組織使用,而且Flutter是徹底免費、開源的。
複製代碼

簡而言之bash

  1. 跨端(移動、Web、桌⾯、嵌⼊式)
  2. ⾼性能(Dart)
  3. ⾼效開發(熱重載)
  4. 富有表現⼒的 UI(Widget)

舒適提示app

  • 搭建開發環境
  • Dart簡介
  • ......

這些咱們都不講,今天咱們聊一下 Flutter Widget 。讓咱們開始吧~框架

Widget 簡介

概念

Widget 描述了在當前的配置和狀態下,視圖所應該 呈現的樣⼦。當 Widget 的狀態改變時,它會從新構 建其描述(展現的 UI),框架則會對⽐先後變化的 不一樣,以肯定底層渲染樹從⼀個狀態轉換到下⼀個狀 態所需的最⼩更改。less

Widget目錄

image

描述元素的配置

示例-1

image

示例-2

image

Widget 結構

image

Widget 組合的結構是樹,因此叫Widget 樹。樹中包含ide

  • 根Widget
    • WidgetsApp【自定義風格】
    • MaterialApp【基於 WidgetsApp的Material Design 風格(經常使用)
    • CupertinoApp【基於 WidgetsApp 實現的 iOS 風格】
  • 父Widget
  • 子Widget
// main.dart
import 'package:flutter/material.dart'; //風格須要先導入哦~
import 'my_home_page_widget.dart';

void main() => runApp(MyApp());  //Flutter會默認把 根Widget 充滿屏幕

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.light(),
      home: MyHomePage(title: 'Vava熊の日記'),
    );
  }
}
複製代碼

Widget 與 Element

  • Widget樹其實是一個配置樹,而真正的UI渲染樹是由Element構成。
  • 一個Widget對象能夠對應多個Element對象。根據同一份配置(Widget),能夠建立多個實例(Element)。
graph LR
Widget配置--> Element1
Widget配置--> Element2
Widget配置--> Element3
Widget配置--> ...
複製代碼

Widget 狀態分類

由於渲染是很耗性能的,爲了提升 Flutter 的幀率,就要儘可能減小沒必要要的 UI 渲染,因此 Flutter 根據 UI 是否有變化,將 Widget 分爲StatelessWidget && StatefulWidget函數

StatelessWidgetStatefulWidget都是直接繼承自Widget類,它們引入了兩種Widget模型,接下來咱們將重點介紹一下這兩個類。性能

StatelessWidget:immutable(狀態不可變)

StatelessWidget是不可變狀態的 Widget 抽象類, 只能在加載/構建 Widget 時才繪製一次,沒法基於任何事件或用戶操做重繪。因此 StatelessWidget生命週期就只有一個,即 build 函數。ui

StatelessWidget の Demo

// main.dart
import 'package:flutter/material.dart';
import 'stateless.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.light(),
      home: MyStatelessApp("123 木頭人,不準動 ——from Vava熊")
    );
  }
}
複製代碼
//stateless.dart
import 'package:flutter/material.dart';

class MyStatelessApp extends StatelessWidget {
  final String content;
  MyStatelessApp(this.content);
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar:AppBar(
          title: Text('StatelessWidget'),
        ),
        body:Center(
          child: Text(content),
        )
    );
  }
}
複製代碼

效果圖

image

StatefulWidget 及 State

  • 可變狀態的 Widget
  • 建立 State 對象
  • 多生命週期

StatefulWidget の Demo

每點擊文本一次,body文本中就會多一次‘贊’this

// main.dart
import 'package:flutter/material.dart';
import 'stateful.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData.light(),
      home: MyStatefulApp("Vava熊の一天")
    );
  }
}
複製代碼
//stateful.dart
import 'package:flutter/material.dart';

class MyStatefulApp extends StatefulWidget {
  String content;
  MyStatefulApp(this.content);

  @override
  State<StatefulWidget> createState() {
    return MyStatefulAppState();
  }
}

class MyStatefulAppState extends State<MyStatefulApp> {
  bool isShowText =true;
  void increment(){
    setState(() {
      widget.content += "贊";
    });
  }
  
  //build() 方法在 didChangeDependencies()(或者 didUpdateWidget() )以後調用
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar:AppBar(
          title: Text('StatefulWidget及State'),
        ),
        body:Center(
          child: GestureDetector(
            child: isShowText? Text(widget.content) :null,
            onTap: increment,
           )
        )
    );
  }
  
  //-------only 生命週期 log------------
  //建立 State 對象後要調用的第一個方法
  @override
  void initState() {
    super.initState();
    print("initState");
    context.runtimeType;
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("didChangeDependencies");
  }

  //runtimeType 和 Widget.key 都同樣,那麼就會調用 didUpdateWidget()。
  @override
  void didUpdateWidget(MyStatefulApp oldWidget) {
    super.didUpdateWidget(oldWidget);
    print("didUpdateWidget");
  }

  // StaefulWidget 從樹中移除時
  @override
  void dispose() {
    super.dispose();
    print("dispose");
  }
  
  //執行 HotReload,就會觸發 reassemble(),這提供了從新初始化在 initState() 方法中準備的任何數據的機會,包括全局變量。
  @override
  void reassemble() {
    super.reassemble();
    print("reassemble");
  }
}
複製代碼

效果圖

image

State 的生命週期

在上面的例子中,除了效果外,咱們也看到了關於生命週期的備註信息。

// 控制檯日誌
// 1.第一次 | 新打開
....
Restarted application in 1,153ms.
flutter: initState
flutter: didChangeDependencies
flutter: reassemble
flutter: didUpdateWidget
...
// 2.咱們點擊⚡️按鈕熱重載
...
Syncing files to device iPhone Xʀ...
flutter: reassemble
flutter: didUpdateWidget
...
// 3. 移除 widget
...
flutter: reassemble
flutter: dispose
Reloaded 2 of 442 libraries in 117ms.
...
複製代碼

盜圖小結

image

葵花寶典:若是 UI 須要改變,就用 StatefulWidget。不須要改變,就用 StatelessWidget。

寫在最後の總結

Widget 特色

  • 一切皆 Widget
  • UI的配置信息
  • 一次性的
  • 輕量的

Widget 應用

Widget 衆多,須要開發者們更多地實踐與性能的關注。 路漫漫其修遠兮,今天也要加油鴨~

關於咱們

快狗打車前端團隊專一前端技術分享,按期推送高質量文章,歡迎關注點贊。
文章同步發佈在公衆號喲,想要第一時間獲得最新的資訊,just scan it !

公衆號二維碼
相關文章
相關標籤/搜索