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

前言

上一篇咱们对 Flutter UI 有了一个基本的了解。bash

这一篇咱们经过自定义 Widget 来了解下如何写一个 Widget?less

然而 Widget 有两个,StatelessWidget 和 StatefulWidget,咱们要继承哪个?ide

下面让咱们跟着文章来探索一番。函数

目录

1. StatelessWidget

咱们先来看下继承的 Widget 为 StatelessWidget 的状况。字体

第一步:新建一个文件 bold_text.dartui

这里文件名后面后缀 .dart 可带可不带this

这里文件名后面后缀 .dart 可带可不带

文件名多个单词组成用下划线分隔。spa

这里咱们演示直接在 lib 文件夹下面建立,实际项目记得文件夹结构的组织哦~3d

第二步:import 系统包code

通常自定义 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 初窥

相关文章
相关标签/搜索