Flutter ListView 局部刷新数据、ListView点赞收藏
题记
—— 执剑天涯,从你的点滴积累开始,所及之处,必精益求精。
Flutter是谷歌推出的最新的移动开发框架。
本文章实现的是 ListView 中 Item 局部数据刷新的效果,如下图所示。
在这只是一个 Demo ,是一个实现思路,在应用开发的更多场景中如 资讯列表的点赞、收藏等等,诸多业务场景都可使用。
1 Demo 实现
首先是这里使用列表使用到的数据模型定义如下:完整源码
///ListView 测试数据 Model
class TestBean {
String name;
bool isCollect;
TestBean({this.name, this.isCollect});
}
然后就是 ListView 实现的主页面,定义如下:
///ListView 局部数据更新使用 Demo
class TestListPartPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _TestABPageState();
}
}
class _TestABPageState extends State {
///测试数据集合
List<TestBean> _testList = [];
@override
void initState() {
super.initState();
///模拟测试数据
for (int i = 0; i < 100; i++) {
_testList.add(TestBean(name: "测试数据 $i", isCollect: false));
}
}
@override
Widget build(BuildContext context) {
///页面主体脚手架
return Scaffold(
appBar: AppBar(
title: Text("ListView 局部数据更新 "),
),
body: buildListView(),
);
}
///构建一个列表 ListView
buildListView() {
///懒加载模式构建
return ListView.builder(
///子Item的构建器
itemBuilder: (BuildContext context, int index) {
///每个子Item的布局
///在这里是封装到了独立的 StatefulWidget
return TestListItemWidget(
///子Item对应的数据
bean: _testList[index],
///可选参数 子Item标识
key: GlobalObjectKey(index),
);
},
///ListView子Item的个数
itemCount: _testList.length,
);
}
}
每个子 Item 的UI布局及功能封装成了一个 独立的 StatefulWidget,代码如下:
///ListView 的子Item
class TestListItemWidget extends StatefulWidget {
///本Item对应的数据模型
final TestBean bean;
TestListItemWidget({@required this.bean, Key key}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _ListItemState();
}
}
class _ListItemState extends State<TestListItemWidget> {
@override
Widget build(BuildContext context) {
return Material(
child: Container(
color: Colors.grey[300],
padding: EdgeInsets.only(
top: 5,
bottom: 5,
),
child: Container(
padding: EdgeInsets.only(
left: 15,
right: 15,
),
color: Colors.white,
height: 60,
child: buildRow(),
),
),
);
}
///内容区域
Row buildRow() {
///左右线性排开
return Row(
children: [
///权重布局 文本占用空白区域
Expanded(
child: Text(
"${widget.bean.name}",
)),
///收藏按钮
RaisedButton(
///按钮的背景
color: widget.bean.isCollect ? Colors.blue : Colors.grey[200],
///点击更新当前 Item 数据以及刷新页面显示
onPressed: () {
setState(() {
widget.bean.isCollect = !widget.bean.isCollect;
});
},
child: Text(
"${widget.bean.isCollect ? '已收藏' : '收藏'}",
style: TextStyle(
color: widget.bean.isCollect ? Colors.white : Colors.red),
),
),
],
);
}
}
2 原理分析
很多个为什么,咱们一一来分析,大家如果有疑问或者不同的看法,可以回复评论,一起优化
2.1 实现的真的是局部刷新吗 ?
答案为 是的,在这里模拟了100条数据,但是这里使用的是懒加载模式构建的,所以实际绘制出来的 Item 并不是 100 条,如下图所示:
滑动时,滑出屏幕外的,超出ListView缓存区域的就会被销毁,在本 Demo 本测试模拟器中,ListView中始终是绘制的 16 个子 Item。
ListView 每一个子 Item 都是一个独立的 StatefulWidget ,都对应的是一个 独立的 State ,所以调用 setState方法来刷新只是刷新了当前的 StatefulWidget 内容区域,当然从源码角度也有另外的解读,这里不去说源码。
当然在实际业务场景中,你的 ListView 中的 Item的UI布局功能可能足够的复杂,不用担心 ,你也可以采用这种思路 ,把每个 Item 中的 部分 Widget 再次封装到不同的StatefulWidget 中,这样也能实现ListView 中一个Item中不同的Widget 刷新不同的区域。
当然 也可以在 ListView 的Item 中使用 Stream 、Provider 、BloC等等,小编这里也有说明点击查看
2.2 状态如何保存的 ???
通过数据模型来保存的状态,因为在这里使用的是根据 TestBean 中 isCollect 的值来构建不同的样式的,List中保存的 TestBean 的标识不同,构建的子Item的样式不同。
2.3 List 中的数据是如何更新的 ???
还是这一句更新的:
setState(() {
widget.bean.isCollect = !widget.bean.isCollect;
});
效果同下
///修改数据
widget.bean.isCollect = !widget.bean.isCollect;
///刷新页面显示
setState(() { });
在这一步修改数据,看下图你就明白了
ListView 的子Item 中(TestListItemWidget)使用的数据模型在内存区域中还是在 TestListPartPage 这里创建的 _testList 集合中保存的对象实体,整个过程中只是通过指针索引来绑定数据,修改数据实际上修改的还是同一块内存区域中的数据。
完毕
以小编的性格,要实现百万Demo随时复制粘贴肯定是需要源码的 github 完整源码 点击查看
当然以小编的性格,肯定是要有视频录制的,目前正在录制中,你可以关注一下 西瓜视频 --- 早起的年轻人 随后会上传
- Python中的单例模式的几种实现方式的及优化
- 程序员学习python必备的4大网站,你用过几个?
- 知面不知心?AI帮你看懂对方的“小心思”
- 数据库连接池,本地线程,上下文管理
- 2018年微信小程序风口趋势预测
- 小程序走在取代APP路上
- 重磅!小程序社交立减金全面开放,快来领攻略
- VR/AR未来何去何从?
- 使用Python+Tensorflow的CNN技术快速识别验证码
- 数字化医院科研信息化管理平台的设计
- 人工智能双刃剑:可协助安全专家,也可带来挑战
- “人工智能+教育”巨浪冲击下,传统的教育理念是否还能幸存?
- 完美世界战略投资多牛传媒,将联手打造泛娱乐媒体矩阵
- 数据恢复-SQL被注入攻击程序的应对策略
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 基于laravel缓冲cache的用法详解
- Python使用sys.exc_info()方法获取异常信息
- laravel通用化的CURD的实现
- Laravel修改验证提示信息为中文的示例
- PHP+redis实现微博的推模型案例分析
- Laravel 解决composer相关操作提示php相关异常的问题
- laravel 实现根据字段不同值做不同查询
- php实现获取近几日、月时间示例
- PHP+redis实现微博的拉模型案例详解
- PHP实现微信申请退款功能
- Laravel+Intervention实现上传图片功能示例
- 关于laravel框架中的常用目录路径函数
- Java byte数组操纵方式代码实例解析
- php桥接模式应用案例分析
- PHP设计模式之中介者模式(Mediator Pattern)入门与应用案例详解