欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2022-04-28 21:57:17
Flutter 即学即用系列博客第五弹来了。 自定义 Widget 让你对 UI 了解更加深入。 还有 dart 语法糖...

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

前言

上一篇我们对 flutter ui 有了一个基本的了解。

这一篇我们通过自定义 widget 来了解下如何写一个 widget?

然而 widget 有两个,statelesswidget 和 statefulwidget,我们要继承哪一个?

下面让我们跟着文章来探索一番。

目录

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

1. statelesswidget

我们先来看下继承的 widget 为 statelesswidget 的情况。

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

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

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

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

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

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

第二步:import 系统包

一般自定义 widget 都要 import 下面的一个包。

import 'package:flutter/material.dart';

ide 有自动提示和补全功能,因此不用死记硬背。

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

第三步:自定义一个类继承自 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 代码即可。如下图:

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

第五步:实现 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 的语法糖简化了写法。具体更多构造函数写法可以查看 。

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

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();
  }
}

效果如下:

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

这里重点的代码是下面:

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 初窥

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