前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter跨平台移动端开发丨Widget、Element、State、状态管理

Flutter跨平台移动端开发丨Widget、Element、State、状态管理

作者头像
码脑
发布2019-05-25 09:09:01
1.7K0
发布2019-05-25 09:09:01
举报
文章被收录于专栏:大前端大前端

目录

  1. Widget
  2. Element
  3. State
  4. 状态管理

Widget 的概念

widget 的主要工作是通过实现 build 函数 来构建自身。一个 widget 通常由一些低级别的 widget 组成,flutter 框架依次的构建这些低级别的 widget,直到构建到最底层的子 widget 时,它会计算并描述 widget 的几何形状

flutter 中所有的对象都是一个 widget 。它既可以表示UI元素(如:Text / Image / Row / Column),也可表示功能性的组件(如:GestureDetectorWidget - 手势检测 / Theme - 数据传递)

Widget 的分类

widget 可分为 无状态的 StatelessWidget 或者是有状态的 StatefulWidget,两者的区别在于状态的改变,需要根据当前widget是否需要管理一些状态来选择使用

StatelessWidget:无状态,比如标题栏中的标题 StatefulWidget:有状态,创建时需要指定一个 State ,在需要更新 UI时调用 setState(VoidCallbackfn),并在 VoidCallback 中改变一些些变量数值等,组件会重新 build 以达到数显状态/UI的效果。代码实例如下:

代码语言:javascript
复制
/**
 * @des StatefulWidget 使用实例 - 计数器
 * @author liyongli 20190409
 * */
class Conunter extends StatefulWidget{

  // 快捷写法
  @override
  _CounterState createState() => new _CounterState();

  /**
   * // 原始写法
   * @override
   * State<StatefulWidget> createState() {
   *    return  new _CounterState();
   * }
   * */

}

/**
 * 计数器操作模块
 * */
class _CounterState extends State<Conunter>{

  // 计数器
  int number = 0;

  // 按钮点击事件监听
  void _numberAdd(){
    setState(() {
      number += 1;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Row(
      children: <Widget>[
        new RaisedButton(
            onPressed: _numberAdd,
            child: new Text("ADD"),
        ),
        new Text("更新数值: $number次")
      ],
    );
  }

}
Widget 支持库

flutter 提供了一套丰富、强大的基础 widget ,在此基础上还提供了Android 默认风格库: Material 与 IOS 风格库:Cupertino。

导入相应的依赖即可使用:

代码语言:javascript
复制
import 'package:flutter/widgets.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
基础 Widget
  • Text:文本
  • Row:水平布局,基于 web Flexbox 布局模型。
  • Column:垂直布局,基于 web Flexbox 布局模型。
  • Stack:取代线性布局,与 Android 中 FrameLayout相似,允许子 widget 堆叠,使用 positioned 定位它们相对于上下左右四条边的位置。基于 web absolute positioning(绝对定位) 布局模型
  • Container:矩形元素,可以装饰 BoxDecoration,如 background、边框、阴影,它可以具有边距(margins)、填充(padding)和应用与其大小的约束(constraints)。Container 可以使用矩阵在三维空间中对其进行变换
Material

遵循 Material Design 规则。以 MaterialAppWidget 开始,包含有 Scaffold、AppBar、FlatButton 等。

使用前需要先引入依赖:

代码语言:javascript
复制
import 'package:flutter/material.dart';

Material 库中有一些 widget 可以根据实际运行平台切换风格,如 MaterialPageRoute,在路由切换时,切换动画会随平台不同而变化

Cupertino

遵循 IOS 应用风格,目前还没有 Material 库丰富。

使用前需要先引入依赖:

代码语言:javascript
复制
import 'package:flutter/cupertino.dart';

由于 Material 和 Cupertino 都是在基础 widget 库之上的,所以如果你的应用中引入了这两者之一,则不需要再引入 flutter/widgets.dart 了,因为它们内部已经引入过了。


Element

widget 中主要包含了组件的配置数据,但它并不代表最终绘制在屏幕上的显示元素,真正代表屏幕上显示元素的是 element,widget 是 element 的配置数据,一个 widget 可同时对应多个 element


State 的概念

每一个 StatefulWidget 类都会对应一个 State 类,State 表示与其对应的 StatefulWidget 要维护的状态,保存的状态信息可以在 build 时被获取,同时,在 widget 生命周期中可以被改变,改变发生时,可以调用其 setState() 方法通知 framework 发生改变,framework 会重新调用 build 方法重构 widget 树,最终完成更新 UI 的目的。

state 中包含两个常用属性:widgetcontextwidget 属性表示当前正在关联的 widget 实例,但关联关系可能会在 widget 重构时发生变化(framework 会动态设置 widget 属性为最新的widget 对象)。context 属性是 buildContext 类的实例,表示构建 widget 的上下文,每个 widget 都有一个自己的 context 对象,它包含了查找、遍历当前 widget 树的方法。

State 的生命周期

  • initState:当前 widget 对象插入 widget树中时调用
  • didChangeDependencies:当前 State 对象的依赖项发生变化时调用
  • build:绘制当前界面布局时调用
  • reassemble:使用热重载时调用
  • didUpdateWidget:widget 配置内容有变动重构时调用
  • deactivate:当前 widget 对象从 widget 树中移出时调用
  • dispose:当前 widget 对象从 widget 树中永久删除时调用

名称

返回值/类型

意义

context read-only

BuildContext

The location in the tree where this widget builds.

mounted read-only

bool

Whether this State object is currently in a tree.

widget read-only

T

The current configuration.

hashCode read-only, inherited

int

The hash code for this object.

runtimeType read-only, inherited

Type

A representation of the runtime type of the object.

build(BuildContext context)

Widget

绘制当前界面布局时调用 / Describes the part of the user interface represented by this widget.

deactivate()

void

当前 widget 对象从 widget 树中移出时调用 / Called when this object is removed from the tree.

debugFillProperties(DiagnosticPropertiesBuilder properties)

void

Add additional properties associated with the node.

didChangeDependencies()

void

当前 State 对象的依赖项发生变化时调用 / Called when a dependency of this State object changes.

didUpdateWidget(T oldWidget)

void

widget 配置内容有变动重构时调用 / Called whenever the widget configuration changes.

dispose()

void

当前 widget 对象从 widget 树中永久删除时调用 / Called when this object is removed from the tree permanently.

initState()

void

当前 widget 对象插入 widget树中时调用 / Called when this object is inserted into the tree.

reassemble()

void

使用热重载时调用 / Called whenever the application is reassembled during debugging, for example during hot reload.

setState (VoidCallback fn)

void

Notify the framework that the internal state of this object has changed.

实际代码测试

代码语言:javascript
复制
/**
 * @des StatefulWidget 使用实例 - 计数器
 * @author liyongli 20190409
 * */
class Conunter extends StatefulWidget{

  // 快捷写法
  @override
  _CounterState createState() => new _CounterState();

  /**
   * // 原始写法
   * @override
   * State<StatefulWidget> createState() {
   *    return  new _CounterState();
   * }
   * */

}

/**
 * 计数器操作模块
 * */
class _CounterState extends State<Conunter>{

  // 计数器
  int number = 0;

  // 按钮点击事件监听
  void _numberAdd(){
    setState(() {
      number += 1;
    });

  }

  @override
  Widget build(BuildContext context) {
    print("widget 绘制 - build");
    return new Row(
      children: <Widget>[
        new RaisedButton(
            onPressed: _numberAdd,
            child: new Text("ADD"),
        ),
        new Text("更新数值: $number次")
      ],
    );
  }

  @override
  void initState() {
    super.initState();
    print("State 创建 - initState");
  }

  @override
    void didUpdateWidget(Conunter oldWidget) {
      super.didUpdateWidget(oldWidget);
      print("widget 重构 - didUpdateWidget");
  }

  @override
  void deactivate() {
    super.deactivate();
    print("State 移出 - deactivate");
  }

  @override
  void dispose() {
    super.dispose();
    print("State 删除 - dispose");
  }

  @override
  void reassemble() {
    super.reassemble();
    print("热重载 - reassemble");
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("State 更改 - didChangeDependencies");
  }

}
  • 首次运行时
代码语言:javascript
复制
I/flutter (28866): State 创建 - initState
I/flutter (28866): State 更改 - didChangeDependencies
I/flutter (28866): widget 绘制 - build
  • 使用热重载时
代码语言:javascript
复制
I/flutter (28866): 热重载 - reassemble
I/flutter (28866): widget 重构 - didUpdateWidget
I/flutter (28866): widget 绘制 - build
  • 更改路由(移除当前 widget)后使用热重载时
代码语言:javascript
复制
I/flutter (28866): 热重载 - reassemble
I/flutter (28866): State 移出 - deactivate
I/flutter (28866): State 删除 - dispose

StatefulWidget 状态管理

管理状态的常见方法:

  • widget 管理自己的 state
  • 父 widget 管理子 widget 状态
  • 混合管理

决定状态管理的原则:

  • 有关用户数据由父 widget 管理
  • 有关界面效果由 widget 本身管理
  • 状态被不同 widget 共享,由他们共同的父 widget 管理

widget 管理自己的 state

代码语言:javascript
复制
/**
 * @des 管理自身状态
 * @author liyongli 20190410
 * */
class TapboxA extends StatefulWidget{

  TapboxA({Key key}):super(key:key);

  @override
  _TapboxAState createState() => new _TapboxAState();

}

/**
 * 颜色变化测试模块
 * */
class _TapboxAState extends State<TapboxA>{

  bool _active = false;

  void _handleTap(){
    setState(() {
      _active = !_active;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new GestureDetector(
      onTap: _handleTap,
      child: new Container(
        child: new Center(
          child: new Text(
            _active ? "Activie"  : "Inactive",
            style: new TextStyle(fontSize: 32.0,color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: new BoxDecoration(
            color: _active ? Colors.lightGreen[700] : Colors.grey[600]
        ),
      ),
    ),
    );
  }
}

父 widget 管理子 widget 状态

代码语言:javascript
复制
/**
 * @des 父 widget 管理子 widget 状态
 * @author liyongli 20190410
 * */
class TapboxBParentWidget extends StatefulWidget {

  @override
  _TapboxBParentState createState() => new _TapboxBParentState();

}

/**
 * 父 widget
 * */
class _TapboxBParentState extends State<TapboxBParentWidget>{

  bool _active = false;

  void _handleTapboxChanged(bool newValue) {
    setState(() {
      _active = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new TapboxB(
        active: _active,
        onChanged: _handleTapboxChanged
      ),
    );
  }
}

/**
 * 子 widget
 * */
class TapboxB extends StatelessWidget{

  TapboxB({Key key, this.active: true, @required this.onChanged})
      : super(key: key);
  ValueChanged<bool> onChanged ;
  bool active;

  void _handleTap(){
      onChanged(!active);
  }

  Widget build(BuildContext context) {
    return new GestureDetector(
      onTap: _handleTap,
      child: new Container(
        child: new Center(
          child: new Text(
            active ? 'Active' : 'Inactive',
            style: new TextStyle(fontSize: 32.0, color: Colors.white),
          ),
        ),
        width: 200.0,
        height: 200.0,
        decoration: new BoxDecoration(
          color: active ? Colors.lightGreen[700] : Colors.grey[600],
        ),
      ),
    );
  }
}

混合管理

代码语言:javascript
复制
/**
 * @des 混合管理
 * @author liyongli 20190410
 * */
class ParentTapboxCWidget extends StatefulWidget{

  @override
  State<StatefulWidget> createState() => new ParentTapboxCState();

}

class ParentTapboxCState extends State<ParentTapboxCWidget>{

  bool _active = false;

  void _handleTapboxChanged(bool newValue){
    setState(() {
      _active = newValue;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Container(
      child: new TapboxCWidget(
        active: _active,
        onChanged: _handleTapboxChanged,
      ),
    );
  }
}

class TapboxCWidget extends StatefulWidget{

  TapboxCWidget({Key key, this.active:false, @required this.onChanged}):super(key:key);
  final bool active;
  final ValueChanged<bool> onChanged;

  @override
  State<StatefulWidget> createState() => new TapboxCState();

}

class TapboxCState extends State<TapboxCWidget>{

  bool _highlight = false;

  void _handleTapDown(TapDownDetails details){
    setState(() {
      _highlight = true;
    });
  }

  void _handleTapUp(TapUpDetails details){
    setState(() {
      _highlight = false;
    });
  }

  void _handleCancel(){
    setState(() {
      _highlight = false;
    });
  }

  void _handleTap(){
    widget.onChanged(!widget.active);
  }


  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      onTapDown: _handleTapDown,
      onTapUp: _handleTapUp,
      onTap: _handleTap,
      onTapCancel: _handleCancel,
      child: new Container(
        child: new Center(
          child: new Text(
            widget.active ? "Active" : "Inactive",
          style: new TextStyle(fontSize: :32.0,color: Colors.white),),
        ),
        width: 200.0,
        height: 200.0,
        decoration: new BoxDecoration(
          color: widget.active ? Colors.lightGreen[700] : Colors.grey[600],
          border: _highlight
              ? new Border.all(
            color: Colors.teal[700],
            width: 10.0,
          )
              : null,
        ),
      ),
    );
  }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.05.24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Widget 的概念
  • Widget 的分类
  • Element
    • State 的概念
      • State 的生命周期
        • StatefulWidget 状态管理
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档