1. 程式人生 > >Flutter入門進階之旅(九)StatelessWidget & StatefullWidget

Flutter入門進階之旅(九)StatelessWidget & StatefullWidget

引言

在前面的學習中我們接觸到了flutter中各種基本元件的使用,也學習了一些常用的佈局排版方式,掌握了根據不同的UI widget合理的選用不同的Layout方式進行佈局,但是我們好像在前面的學習中所有的UI都是靜態的,沒有任何互動式的體驗,換句話說我們在之前所掌握的flutter知識都是比較死板的靜態UI頁,缺少了那麼一點靈動性,那今天這篇文章就算是一個過渡,今天我會帶領大家簡單認識下flutter中的動態頁。

佈局對比

細心的讀者可能有留意到在之前我們的講解中大部分頁的根widget都是繼承StatelessWidget,像我們之前講Text、Image、各種Layout,包括上一節講Button的時候

class TextPage extends StatelessWidget{
....
class ImagePage extends StatelessWidget {
...
class LayoutPage extends StatelessWidget {
...
class LayoutPage extends StatelessWidget {
...

但是在講TextField這一節的時候我們的根widget繼承的卻是StatefullWidget

class TextFieldPage extends StatefulWidget {
...

思考
一臉懵逼

1.這會有什麼不一樣嗎?
2.這跟今天的課程有什麼關係呢?
3.我應該如何選擇,或者我怎麼確定何時選用那種根Widget呢?

關於StatelessWidget跟StatefullWidget

關於StatelessWidget跟StatefullWidget網上一搜一大推類似的博文介紹,我不想再走老套路,把官方的翻譯貼出來,然後大家看完之後還是雲裡霧裡的不知所以然,我想把今天的分享搞的輕鬆跟通俗一點,不會這麼的官方也不會那麼的晦澀,我從我個人的理解出發去分析此二者的區別。

其實上面提到的疑惑我相信大多數剛接觸flutter的讀者應該都會有類似的想法,我們怎麼區別二者,何時如何選用二者中的某一個呢?我結合咱們之前的分享用求同存異的觀點看問題吧,細心的讀者可能會發現我們之前的分像Text、Image、Button、各種Layout、甚至包括GestureDetector這些章節的分享,我們繪製的UI頁都是靜態的,換句話說就是一旦這些UI頁被成功渲染之後就不需要頁不可能去改變他的狀態,就是一開始是什麼樣就是什麼樣,在UI上沒有任何的變化。

程式碼分析

舉個例子

場景一:我要在UI上顯示一串文字,這串文字從始至終都不需要改變,也不可能會改變,這種場景下跟佈局就需要選用StatelessWidget

import 'package:flutter/material.dart';

class TextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Hello Flutter"),
        ),
        body: new Center(
          child: new Text(
            "我從UI被渲染完成之後就這個狀態,不可能發生改變",
            style: new TextStyle(fontSize: 18.0),
            textAlign: TextAlign.center,
          ),
        ));
  }
}

效果圖
StatelessWidget

如上圖,這串文字從一開始就是這樣,也永遠是這樣,這種場景下你就可以選擇用StatelessWidget來渲染你的根佈局,當然用StatefullWidget也能完成,但是需要用StatefullWidget實現的佈局用StatelessWidget是不能完成的。

場景二:UI頁上有一個按鈕,我每次點選按鈕UI頁上的Text顯示內容加1

這種情況下,我們很清楚的知道當前的UI頁是不固定的,換句話說,UI頁上的控制元件可能會在某一個時刻或者某種邏輯狀態下改變自身的狀態,那這個時候StatelessWidget顯然是不能完成這一要求的,我們來用StatefullWidget模擬上場景二的具體實現。

效果圖
StatefWidget

示例程式碼

import 'package:flutter/material.dart';

class TextPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MyState();
}

class MyState extends State<TextPage> {
  var _count = 0;

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Hello StatefulWidget"),
        ),
        body: new Stack(
          children: <Widget>[
            new Align(
              child: new Text(
                "當前count值:$_count",
                style: new TextStyle(fontSize: 18.0),
                textAlign: TextAlign.center,
              ),
            ),
            new Align(
              alignment: new FractionalOffset(0.5, 0.0),
              child: new MaterialButton(
                color: Colors.blueAccent,
                textColor: Colors.white,
                onPressed: () {
                  //重新渲染當前UI頁的狀態
                  setState(() {
                    _count++;
                  });
                },
                child: new Text('點我加下方文字自動加1'),
              ),
            ),
          ],
        ));
  }
}

通過上述程式碼我們得知在StatefullWidget中通過setState通知重新渲染當前UI頁上的所有Widget來完成改變狀態。

總結

通過今天的學習我們從原先死板的UI靜態頁過渡到了狀態可改變的UI繪製,瞭解到了StatelessWidget和StatefullWidget的區別,並且能根據不同的UI繪製場景合理的選用不同的根Widget,比如我們所要繪製的UI頁的狀態包括被渲染的內容都是始終不變的,那我們會選用StatelessWidget來完成,如果所繪製的UI可能在未來的某個場景下發生變化我們會選用StatefullWidget來實現。