总结之前学习的概念,编写一个完整的应用实例。假设我们使用一个网络购物的应用程序,它展示出售的各种商品和存放准备购买商品的购物车。首先定义一个展示类ShoppingListItem.dart:

import 'package:flutter/material.dart';
class Product {const Product({this.name});final String name;
}
typedef void CartChangedCallback(Product product, bool inCart);
class ShoppingListItem extends StatelessWidget {ShoppingListItem({Product product, this.inCart, this.onCartChanged}): product = product,super(key: new ObjectKey(product));final Product product;final bool inCart;final CartChangedCallback onCartChanged;Color _getColor(BuildContext context) {return inCart ? Colors.black54 : Theme.of(context).primaryColor;}TextStyle _getTextStyle(BuildContext context) {if (!inCart) return null;return new TextStyle(color: Colors.black54,decoration: TextDecoration.lineThrough,);}@overrideWidget build(BuildContext context) {return new ListTile(onTap: () {onCartChanged(product, !inCart);},leading: new CircleAvatar(backgroundColor: _getColor(context),child: new Text(product.name[0]),),title: new Text(product.name, style: _getTextStyle(context)),);}
}

ShoppingListItem控件遵循无状态控件的通用模式,将在构造函数中接收到的值存储在final成员变量中,然后在build函数执行时使用。例如布尔值inCart在两个视觉效果之间切换:一个使用当前主题的颜色,另一个使用灰色。

当用户点击列表项时,控件不会直接修改inCart的值,但是控件从父控件接收onCartChanged函数。此模式允许你在控件较高的层次结构中存储状态,这样使状态的持续时间更长。在极端情况下,存储在runApp的控件状态在应用程序的生命周期内保持不变。

当父控件接收到onCartChanged回调,父控件会更新其内部状态,这将触发父控件重建并使用新的inCart值创建ShoppingListItem的新实例。尽管父控件在重建时创建了ShoppingListItem的新实例,但该操作很节省,因为框架会将新构建的控件与之前构建的控件时进行比较,并将有差异的部分应用于底层渲染对象。

下面编写存储可变状态的父控件:

import 'package:flutter/material.dart';
import 'ShoppingListItem.dart';
class ShoppingList extends StatefulWidget {ShoppingList({Key key, this.products}) : super(key: key);final List<Product> products;@override_ShoppingListState createState() => new _ShoppingListState();
}
class _ShoppingListState extends State<ShoppingList> {Set<Product> _shoppingCart = new Set<Product>();void _handleCartChanged(Product product, bool inCart) {setState(() {if (inCart)_shoppingCart.add(product);else_shoppingCart.remove(product);});}@overrideWidget build(BuildContext context) {return new Scaffold(appBar: new AppBar(title: new Text('购物清单'),),body: new ListView(children: widget.products.map((Product product) {return new ShoppingListItem(product: product,inCart: _shoppingCart.contains(product),onCartChanged: _handleCartChanged,);}).toList(),),);}
}
final List<Product> _kProducts = <Product>[new Product(name: '鸡蛋'),new Product(name: '面粉'),new Product(name: '巧克力脆片'),
];
void main() {runApp(new MaterialApp(title: 'Flutter教程',home: new ShoppingList(products: _kProducts),),);
}

类ShoppingList继承了StatefulWidget,这意味着这个控件存储可变状态,当ShoppingList首次插入到树中,框架调用createState函数在树中相关联的位置创建一个新的_ShoppingListState实例(注意:通常命名中带有下划线的State子类,说明它们是私有类)。当该控件的父控件重建时,父控件会创建一个新的ShoppingList实例,但框架将重用已经在树上的_ShoppingListState实例,而不会再次调用createState函数。

要访问当前ShoppingList的属性,_ShoppingListState可以使用其config属性。如果父控件重建并创建一个新的ShoppingList,_ShoppingListState也将使用新的config值重建。如果想要在config属性更改时收到通知,可以覆盖didUpdateConfig函数,它通过oldConfig将旧配置与当前config进行比较。

当处理onCartChanged回调时,_ShoppingListState通过从_shoppingCart中添加或删除一个产品来改变其内部状态。为了向框架通知它改变了内部状态,它在setState中封装这些调用。调用setState将控件标记为dirty,并安排它在应用程序下次需要更新屏幕时重建。如果在修改控件内部状态时忘记调用setState,框架不会知道控件是dirty的,可能不会调用控件的build函数,这意味着用户界面不会更新以反映更改的状态。

通过这种方式管理动态,不再需要单独编写代码来创建和更新子控件。相反,只需要实现构建函数,即可处理这两种情况。

Flutter基础—应用实例相关推荐

  1. Flutter基础—你好,Flutter!

    什么是Flutter Flutter是一个移动应用程序的软件开发工具包(SDK),用一个代码库构建高性能.高保真的iOS和Android应用程序.目标是使开发人员能够为Android和iOS提供自然的 ...

  2. Flutter基础(四)开发Flutter应用前需要掌握的Basic Widget

    本文首发于公众号「刘望舒」 关联系列 ReactNative入门系列 React Native组件 Flutter基础系列 前言 学完了Dart语言,接下来就可以学习Widget了,Flutter的U ...

  3. Flutter基础篇(2)-- 老司机用一篇博客带你快速熟悉Dart语法

    版权声明:本文为博主原创文章,未经博主允许不得转载.https://www.jianshu.com/p/3d927a7bf020 转载请标明出处: https://www.jianshu.com/p/ ...

  4. 一份超级详细的Flutter基础组件练习示例,请查收!

    学习B站技术胖的flutter基础课程整理的示例,为了平时方便查阅,同时希望能和大家一同进步~ Flutter基础组件 Hello world import 'package:flutter/mate ...

  5. Flutter基础(三)Dart快速入门

    本文首发于公众号「刘望舒」 关联系列 ReactNative入门系列 React Native组件 Flutter基础系列 前言 Dart是Flutter SDK指定的语言,因此要学习Flutter, ...

  6. 《Dreamweaver CS6完美网页制作——基础、实例与技巧从入门到精通》——1.3 常用网页设计软件...

    本节书摘来自异步社区<Dreamweaver CS6完美网页制作--基础.实例与技巧从入门到精通>一书中的第1章,第1.3节,作者:何新起 更多章节内容可以访问云栖社区"异步社区 ...

  7. Nginx基础配置实例需求分析

    前面我们已经对Nginx服务器默认配置文件的结构和涉及的基本指令做了详细的阐述.通过这些指令的合理配置,我们就可以让一台Nginx服务器正常工作,并且提供基本的web服务器功能. 接下来我们将通过一个 ...

  8. matlab基础与实例教程,MATLAB基础与实例教程

    系统全面,实例丰富 考虑到Matlab进行仿真和运算分析时的基础知识和实践操作,讲解从基础的变量.函数.数据类型等入手,涉及到数学分析.图形可视化.Simulink仿真.文件读写等,全面地介绍了Mat ...

  9. nginx ---- Nginx服务器基础配置实例

    前面我们已经对Nginx服务器默认配置文件的结构和涉及的基本指令做了详细的阐述.通过这些指令的合理配置,我们就可以让一台Nginx服务器正常工作,并且提供基本的web服务器功能. 接下来我们将通过一个 ...

最新文章

  1. i.MX6UL: i.MX 6UltraLite处理器 - 低功耗,安全,Arm® Cortex®-A7内核
  2. pytorch 半精度,提升pytorch推理性能
  3. 如何正确的进行网站入侵渗透测试
  4. 【CyberSecurityLearning 63】CSRF攻击
  5. Prefix Sum Primes
  6. LeetCode 1042. 不邻接植花(图的数据结构)
  7. 个人vscode插件配置全记录
  8. 总结之Unix的基础知识
  9. 电力系统——基于10机39节点的电力系统仿真(Matlab)
  10. 单播、多播(组播)和广播的区别
  11. java制作数字彩虹雨的代码,canvas+gif.js打造自己的数字雨头像的示例代码
  12. myd导入mysql_数据库是.frm,.myd,myi备份如何导入mysql
  13. 美国主要经济数据解注释
  14. 什么是arXiv.org?
  15. android build.prop的参数
  16. C语言-字符0、数字0和‘\0’的区别
  17. 计算机控制室防火危险级为,8.2 空气调节 - 【已作废】火力发电厂与变电站设计防火规范 GB50229-2006 - 消防规范大全 - 消防资源网!...
  18. idea安装plantuml插件画流程图
  19. python搭建内网网站,python搭建服务器
  20. C#中的static,interface,virtual,abstract,override的用法

热门文章

  1. 如何找到适合结婚的女朋友
  2. Altium AD20批量修改丝印大小、更改丝印字体、丝印显示中文、更改位号丝印 相对元件的位置
  3. 【JVM】强引用、软引用、弱引用、虚引用分别是什么
  4. ActionScript读取XML的路径问题
  5. java解析xml文件
  6. VC-SDK路报(预备知识与概念介绍)
  7. sqlservr.exe占用大量内存
  8. c++并发编程基础(一):并发、并行域多线程
  9. 永久修改VS include目录
  10. 结构体,文件操作,指针,简单练习