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

来源:https://www.cnblogs.com/nesger/archive/2019/02/20/10408579.html
-Advertisement-
Play Games

Flutter 即學即用系列博客第五彈來了。 自定義 Widget 讓你對 UI 瞭解更加深入。 還有 dart 語法糖


前言

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

這一篇我們通過自定義 Widget 來瞭解下如何寫一個 Widget?

然而 Widget 有兩個,StatelessWidget 和 StatefulWidget,我們要繼承哪一個?

下麵讓我們跟著文章來探索一番。

目錄

1. StatelessWidget

我們先來看下繼承的 Widget 為 StatelessWidget 的情況。

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

這裡文件名後面尾碼 .dart 可帶可不帶

這裡文件名後面尾碼 .dart 可帶可不帶

文件名多個單片語成用下劃線分隔。

這裡我們演示直接在 lib 文件夾下麵創建,實際項目記得文件夾結構的組織哦~

第二步: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 初窺


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • redis-3.2.6配置文件 主要修改配置文件幾個大方面: 埠 port 安全: bind ip 綁定監聽IP 安全模式開啟與否 protected-mode 一般設置yes 訪問密碼 requirepass 如果設置了bind 127.0.0.1 本地訪問,那麼可以不設置密碼,如果是提供bin ...
  • 安裝下載redis,參考官方文檔:https://redis.io/download 下載: shell>wget http://download.redis.io/releases/redis-3.2.6.tar.gz # 這裡版本讀者應該已官方最新stable版本為準 Notice:我使用的安裝 ...
  • 一、安裝redis 第一步:下載redis安裝包 wget http://download.redis.io/releases/redis-4.0.6.tar.gz 第二步:解壓壓縮包 tar -zxvf redis-4.0.6.tar.gz 第三步:yum安裝gcc依賴 yum install g ...
  • 2.1 資料庫和資料庫表的創建 ①資料庫的創建(在資料庫系統中劃分一塊存儲數據的空間): ②資料庫表的創建 註意: 資料庫 (1)在①中,[ charset 字元集 ] 是可選的,用於設定資料庫的預設字元集,即資料庫存儲使用的字元集。當不聲明時,預設繼承伺服器的字元集 utf-8。 (2)關於字元集 ...
  • 1.安裝 xtrabackup 工具包 下載percona yum源 https://www.percona.com/redir/downloads/percona-release/redhat/percona-release-0.1-4.noarch.rpm 通過 yum 方式安裝 percona ...
  • 本文由雲+社區發表 作者:騰訊雲資料庫 Introduction 導言 任何看到顯著增長的應用程式或網站,最終都需要進行擴展,以適應流量的增加。以確保數據安全性和完整性的方式進行擴展,對於數據驅動的應用程式和網站來說十分重要。人們可能很難預測某個網站或應用程式的流行程度,也很難預測這種流行程度會持續 ...
  • LOGO The tags of features: 開源,記憶體數據存儲,被用作為資料庫,cache and message 中間人/中間件 一個實例:單進程(無子進程),單線程,I/O多路復用( multiplexing and non-blocking I/O)處理客戶端的TCP連接。 支持的數 ...
  • 本文用來介紹Foundation框架的相關知識,以及Foundation框架所提供類的相關知識總結。 1. 框架介紹 框架是由很多類、方法、函數和文檔按照一定的邏輯組織起來的集合,以使開發程式變得更加容易。在OS X系統下有100多個框架,這些框架可以用來開發應用程式。 2. Foundation框 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...