Flutter 即學即用系列博客——05 StatelessWidget vs StatefulWidget

前言

上一篇咱們對 Flutter UI 有了一個基本的瞭解。less

這一篇咱們經過自定義 Widget 來了解下如何寫一個 Widget?ide

然而 Widget 有兩個,StatelessWidget 和 StatefulWidget,咱們要繼承哪個?函數

下面讓咱們跟着文章來探索一番。字體

目錄

1. StatelessWidget

咱們先來看下繼承的 Widget 爲 StatelessWidget 的狀況。ui

第一步:新建一個文件 bold_text.dartthis

這裏文件名後面後綴 .dart 可帶可不帶3d

這裏文件名後面後綴 .dart 可帶可不帶

文件名多個單詞組成用下劃線分隔。code

這裏咱們演示直接在 lib 文件夾下面建立,實際項目記得文件夾結構的組織哦~blog

第二步:import 系統包繼承

通常自定義 Widget 都要 import 下面的一個包。

import 'package:flutter/material.dart';

IDE 有自動提示和補全功能,所以不用死記硬背。

第三步:自定義一個類繼承自 StatelessWidget

通常類名跟文件名一致就能夠,採用駝峯格式命名。

import 'package:flutter/material.dart';

class BoldText extends StatelessWidget {
  
}

第四步:實現一個須要 override 的方法 build

import 'package:flutter/material.dart';

class BoldText extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return null;
  }

}

通常第三步操做以後 IDE 有提示,直接使用快捷修復自動追加 build 代碼便可。以下圖:

第五步:實現 Widget

上述代碼的 TODO 表示咱們要在裏面實現對應的 Widget。因此咱們刪除 TODO,而後在寫咱們要返回的 Widget 來替換 null 便可。

咱們寫一個單獨的方法 **_buildWidget** 來返回 Widget,同時返回咱們以前寫的 Text,以下:

import 'package:flutter/material.dart';

class BoldText extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return _buildWidget();
  }

  Widget _buildWidget() {
    return Text(
      'Hello, world!',
      textDirection: TextDirection.ltr,
      textAlign: TextAlign.center,
      overflow: TextOverflow.ellipsis,
      style: TextStyle(fontWeight: FontWeight.bold),
    );
  }

}

能夠看到咱們這個 Widget 應該會顯示成上篇咱們界面所見的粗體文本。

可是這裏 Hello, world! 寫死了,咱們要讓這個自定義 Widget 通用一些,能夠定義一個必傳參數文本內容,修改以下:

import 'package:flutter/material.dart';

class BoldText extends StatelessWidget {

  final String data;

  BoldText(this.data);

  @override
  Widget build(BuildContext context) {
    return _buildWidget();
  }

  Widget _buildWidget() {
    return Text(
      data,
      textDirection: TextDirection.ltr,
      textAlign: TextAlign.center,
      overflow: TextOverflow.ellipsis,
      style: TextStyle(fontWeight: FontWeight.bold),
    );
  }

}

能夠看到咱們定義了一個變量,經過構造函數讓外部傳進來。

這裏的 BoldText(this.data); 等價於 Android 下面代碼:

BoldText(String data) {
        this.data = data;
    }

能夠看到 dart 的語法糖簡化了寫法。具體更多構造函數寫法能夠查看 dart 官網

2. 自定義 Widget 使用

咱們以以前的 main.dart 爲例進行講解。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        'Hello, world!',
        textDirection: TextDirection.ltr,
        textAlign: TextAlign.center,
        overflow: TextOverflow.ellipsis,
        style: TextStyle(fontWeight: FontWeight.bold),
      ),
    );
  }
}

第一步:導入咱們的自定義 Widget 包

相對路徑:

import 'bold_text.dart';

絕對路徑:

import 'package:my_flutter/bold_text.dart';

上面任選其一便可。主要是相對路徑和絕對路徑的區別。

第二步:使用

import 'package:flutter/material.dart';

import 'bold_text.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: BoldText('Hello, world!'),
    );
  }
}

對比能夠看到節省了不少代碼行,尤爲對於有多個地方用到的公共組件更加能夠這樣處理。

3. StatelessWidget 通用模板

FileName爲你文件名的駝峯形式:

import 'package:flutter/material.dart';

class FileName extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return _buildWidget();
  }

  Widget _buildWidget() {
    //TODO build your widget
  }

}

4. StatefulWidget

咱們再來看下繼承的 Widget 爲 StatefulWidget 的狀況。

第一步:新建 increment.dart 文件

第二步:import 系統包

第三步:自定義一個類繼承自 StatefulWidget

第四步:實現一個須要 override 的方法 createState

到這裏就有點不同了。咱們先看下目前的代碼。

import 'package:flutter/material.dart';

class Increment extends StatefulWidget{

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return null;
  }

}

和 StatelessWidget 不同,這裏不是返回 Widget。

咱們看下如何操做。

第五步:建立一個類繼承 State< T extends StatefulWidget>

這裏咱們建立 _IncrementState 類繼承 State< Increment>,這裏尖括號<>裏面的類型就是咱們一開始寫的繼承自 StatefulWidget 的類 Increment。

而後咱們須要實現一個須要 override 的方法 build。

到這裏是否是就是很熟悉了。

直接看代碼:

import 'package:flutter/material.dart';

class Increment extends StatefulWidget{

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

}

class _IncrementState extends State<Increment> {

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return null;
  }

}

因此接下來的工做就是相似的。

第六步:實現 Widget

參考一開始的例子咱們簡單寫出下面代碼:

import 'package:flutter/material.dart';

class Increment extends StatefulWidget{

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

}


class _IncrementState extends State<Increment> {

  int _count = 0;

  void _incrementCount() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return _buildPage();
  }

  Widget _buildPage() {
    return MaterialApp(
      home: Scaffold(
        body: Center( 
            child : Text('$_count')
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCount,
          tooltip: 'Increment',
          child: Icon(Icons.add),
        ),
      ),
    );
  }
  
}

這裏面須要說明的是多了一個新的 Widget FloatingActionButton。

能夠看到它是做爲 Scaffold 自帶的一個屬性的。

FloatingActionButton 講解:

onPressed 後面是這個按鈕點擊以後會回調的一個方法。

tooltip 是長按以後會顯示的提示文字。

child 是這個按鈕顯示的圖標。

咱們修改 main.dart 文件以下,看下效果:

import 'package:flutter/material.dart';

import 'increment.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Increment();
  }
}

效果以下:

這裏重點的代碼是下面:

setState(() {
      _count++;
});

它表示將數字加一以後更新界面。

須要更新界面時須要調用 setState 方法。

更新數據源能夠在 setState 方法裏面寫。

5. StatefulWidget 通用模板

FileName爲你文件名的駝峯形式,_FileNameState 裏面的 FileName 也是哦~

import 'package:flutter/material.dart';

class FileName extends StatefulWidget{

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

}

class _FileNameState extends State<FileName> {

  @override
  Widget build(BuildContext context) {
    return _buildPage();
  }

  Widget _buildPage() {
    //TODO build your widget
  }
  
}

到了這裏你回過頭去看新建 Flutter 項目時自動建立的 main.dart 文件就看得懂了。

6. StatelessWidget vs StatefulWidget

好了,上面講解完了 StatelessWidget 和 StatefulWidget,相信你們應該知道如何自定義一個 Widget 了,也知道如何在其餘頁面引入了。

可是咱們實際上在使用的時候究竟是要繼承 StatelessWidget 仍是 StatefulWidget 呢?

其實根據名稱能夠看出取決於你這個 Widget 是有狀態仍是無狀態?

不過「狀態」這個詞也不是好理解。

因此筆者是這樣來區分使用 StatelessWidget 仍是 StatefulWidget的?

看界面是否須要更新

好比咱們上面的例子,點擊按鈕文本更新了,因此咱們選擇了 StatefulWidget。

而第一個只是字體調整,界面渲染以後再也不須要更新了,因此咱們選擇了 StatelessWidget。

因此咱們能夠認爲當界面須要更新時,咱們的自定義 Widget 就要繼承 StatefulWidget 而不是 StatelessWidget。

更多閱讀:
Flutter 即學即用系列博客——01 環境搭建
Flutter 即學即用系列博客——02 一個純 Flutter Demo 說明
Flutter 即學即用系列博客——03 在舊有項目引入 Flutter
Flutter 即學即用系列博客——04 Flutter UI 初窺

相關文章
相關標籤/搜索