【致程序猿】Flutter 之 可滚动组件子项缓存 KeepAlive

43 篇文章 2 订阅
6 篇文章 1 订阅

可滚动组件中缓存指定子项的通用方案

在介绍 ListView 时,有一个addAutomaticKeepAlives 属性我们并没有介绍,如果addAutomaticKeepAlivestrue,则 ListView 会为每一个列表项添加一个 AutomaticKeepAlive 父组件。

虽然 PageView 的默认构造函数和 PageView.builder 构造函数中没有该参数,但它们最终都会生成一个 SliverChildDelegate 来负责列表项的按需加载。

而在 SliverChildDelegate 中每当列表项构建完成后,SliverChildDelegate 都会为其添加一个 AutomaticKeepAlive 父组件。下面我们就先介绍一下 AutomaticKeepAlive 组件。

1. AutomaticKeepAlive

AutomaticKeepAlive 的组件的主要作用是将列表项的根 RenderObject 的 keepAlive 按需自动标记 为 true 或 false。为了方便叙述,我们可以认为根 RenderObject 对应的组件就是列表项的根 Widget,代表整个列表项组件,同时我们将列表组件的 Viewport区域 + cacheExtent(预渲染区域)称为加载区域 :

当 keepAlive 标记为 false 时,如果列表项滑出加载区域时,列表组件将会被销毁。
当 keepAlive 标记为 true 时,当列表项滑出加载区域后,Viewport 会将列表组件缓存起来;当列表项进入加载区域时,Viewport 从先从缓存中查找是否已经缓存,如果有则直接复用,如果没有则重新创建列表项。
那么 AutomaticKeepAlive 什么时候会将列表项的 keepAlive 标记为 true 或 false 呢?答案是开发者说了算!Flutter 中实现了一套类似 C/S 的机制,AutomaticKeepAlive 就类似一个 Server,它的子组件可以是 Client,这样子组件想改变是否需要缓存的状态时就向 AutomaticKeepAlive 发一个通知消息(KeepAliveNotification),AutomaticKeepAlive 收到消息后会去更改 keepAlive 的状态,如果有必要同时做一些资源清理的工作(比如 keepAlive 从 true 变为 false 时,要释放缓存)。

我们基于上一节 PageView 示例,实现页面缓存,根据上面的描述实现思路就很简单了:让Page 页变成一个 AutomaticKeepAlive Client 即可。为了便于开发者实现,Flutter 提供了一个 AutomaticKeepAliveClientMixin ,我们只需要让 PageState 混入这个 mixin,且同时添加一些必要操作即可:


class _MSPageItemState extends State<MSPageItem>
    with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    // super.build(context);
    print("flutter build ${widget.text}");
    return Center(child: Text(widget.text!, textScaleFactor: 5.0));
  }

  @override
  bool get wantKeepAlive => true;
}

代码很简单,我们只需要提供一个 wantKeepAlive,它会表示 AutomaticKeepAlive 是否需要缓存当前列表项;

现在我们重新运行一下示例,发现每个 Page 页只会 build 一次,缓存成功了。

2. KeepAliveWrapper

虽然我们可以通过 AutomaticKeepAliveClientMixin 快速的实现页面缓存功能,但是通过混入的方式实现不是很优雅,因为必须更改 Page 的代码,有侵入性,这就导致不是很灵活,比如一个组件能同时在列表中和列表外使用,为了在列表中缓存它,则我们必须实现两份。

wendux 大神提供了一个KeepAliveWrapper组件,如果哪个列表项需要缓存,只需要使用 KeepAliveWrapper 包裹一下它即可

@override
Widget build(BuildContext context) {
  var children = <Widget>[];
  for (int i = 0; i < 6; ++i) {
    //只需要用 KeepAliveWrapper 包装一下即可
    children.add(KeepAliveWrapper(child:Page( text: '$i'));
  }
  return PageView(children: children);
}

下面是 KeepAliveWrapper 的实现源码:


class KeepAliveWrapper extends StatefulWidget {
  const KeepAliveWrapper(
      {Key? key, @required this.child, this.keepAlive = true})
      : super(key: key);

  final Widget? child;
  final bool keepAlive;

  @override
  State<KeepAliveWrapper> createState() => _KeepAliveWrapperState();
}

class _KeepAliveWrapperState extends State<KeepAliveWrapper>
    with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    return widget.child!;
  }

  @override
  bool get wantKeepAlive => widget.keepAlive;

  @override
  void didUpdateWidget(covariant KeepAliveWrapper oldWidget) {
    if (oldWidget.keepAlive != widget.keepAlive) {
      // keepAlive 状态需要更新,实现在 AutomaticKeepAliveClientMixin 中
      updateKeepAlive();
    }
    super.didUpdateWidget(oldWidget);
  }
}


测试下

class KeepAliveDemo extends StatelessWidget {
  const KeepAliveDemo({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return PageView.builder(
      itemCount: 5,
      itemBuilder: (BuildContext ctx, int index) {
        return KeepAliveWrapper(
          child: PageItem(text: "$index"),
          keepAlive: true,
        );
      },
    );
  }
}

class PageItem extends StatelessWidget {
  PageItem({this.text});
  final String? text;
  @override
  Widget build(BuildContext context) {
    print("flutter build ${text}");
    return Center(child: Text(text!, textScaleFactor: 5.0));
  }
}


运行发现,keepAlive为true时每个Item都缓存了,为false时,每个Item都会重新创建,OK。

本文转自 https://www.jianshu.com/p/47acfb0d74f6,如有侵权,请联系删除。

有需要更多完整学习资料的,可以扫描下方二维码领取资料!

Flutter技术解析与实战,全家桶学习资料(含Flutter进阶学习笔记、入门与实战和完整开发实战详解)

Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。

在这里为了方便大家系统的学习Flutter,这里特意联合了阿里P7架构师和谷歌技术团队共同整理了一份Flutter全家桶学习资料。

内容概要:Flutter技术解析与实战、Flutter进阶学习笔记、Flutter入门与实战和Flutter完整开发实战详解。

内容特点:条理清晰,含图像化表示更加易懂。

由于文章内容比较多,篇幅有限,资料已经被整理成了PDF文档,有需要 Flutter技术解析与实战 完整文档的可扫描下方卡片免费获取!

《Flutter技术解析与实战》

目录

img

第一章 混合工程

​ ● Flutter工程体系

​ ● 混合工程改造实战

​ ● 混合工程与持续集成

​ ● 快速完成混合工程搭建

​ ● 使用混合栈框架开发

img

第二章 能力增强

​ ● 基于原生能力的插件扩展

​ ● 基于外接纹理的同层渲染

​ ● 多媒体能力扩展实践

​ ● 富文本能力应用实践

img

第三章 业务架构设计

​ ● 应用框架设计实践

​ ● 轻量级动态化渲染引擎的设计

​ ● 面向切面编程的设计实践

​ ● 高性能的动态模板渲染实践

img

第四章 数据统计与性能

​ ● 数据统计框架的设计

​ ● 性能稳定性监控方案的设计

​ ● 高可用框架的设计与实践

​ ● 跨端方案性能对比实践

img

第五章 企业级应用实战

​ ● 基于Flutter的端结构演进与创新

​ ● Flutter与FaaS云端一体化架构

img

由于文章内容比较多,篇幅有限,资料已经被整理成了PDF文档,有需要 Flutter技术解析与实战 完整文档的可扫描下方卡片免费获取!

《Flutter进阶学习笔记》

目录

img

img

第一章 为什么 Flutter 是跨平台开发的终极之选

​ ● 这是为什么?

​ ● 跨平台开发

​ ● 什么是Flutter

​ ● Flutter特性

​ ● Flutter 构建应用的工具

​ ● 使用 Flutter 构建的热门应用

​ ● 构建 Flutter 应用的成本

img

第二章 在Windows上搭建Flutter开发环境

​ ● 使用镜像

​ ● 系统要求

​ ● 获取Flutter SDK

​ ● 编辑器设置

​ ● Android设置

​ ● 起步: 配置编辑器

​ ● 起步: 体验

​ ● 体验热重载

img

第三章 编写您的第一个 Flutter App

​ ● 创建 Flutter app

​ ● 使用外部包(package)

​ ● 添加一个 有状态的部件(Stateful widget)

​ ● 创建一个无限滚动ListView

​ ● 添加交互

​ ● 导航到新页面

​ ● 使用主题更改UI

img

第四章 Flutter开发环境搭建和调试

​ ● 开发环境的搭建

​ ● 模拟器的安装与调试

​ ● 开发环境的搭建

​ ● 模拟器的安装与调试

img

第五章 Dart语法篇之基础语法(一)

​ ● 简述

​ ● Hello Dart

​ ● 数据类型

​ ● 变量和常量

​ ● 集合(List、Set、Map)

​ ● 流程控制

​ ● 运算符

​ ● 异常

​ ● 函数

​ ● 总结

img

第六章 Dart语法篇之集合的使用与源码解析(二)

​ ● List

​ ● Set

​ ● Map

​ ● Queue

​ ● LinkedList

​ ● HashMap

​ ● Map、HashMap、LinkedHashMap、SplayTreeMap区别

​ ● 命名构造函数from和of的区别以及使用建议

img

第七章 Dart语法篇之集合操作符函数与源码分析(三)

​ ● 简述

​ ● Iterable

​ ● forEach

​ ● map

​ ● any

​ ● every

​ ● where

​ ● firstWhere和singleWhere和lastWhere

​ ● join

​ ● take

​ ● takeWhile

​ ● skip

​ ● skipWhile

​ ● follwedBy

​ ● expand

​ ● reduce

​ ● elementAt

img

第八章 Dart语法篇之函数的使用(四)

​ ● 简述

​ ● 函数参数

​ ● 匿名函数(闭包,lambda)

​ ● 箭头函数

​ ● 局部函数

​ ● 顶层函数和静态函数

​ ● main函数

​ ● Function函数对象

img

第九章 Dart语法篇之面向对象基础(五)

​ ● 简述

​ ● 属性访问器(accessor)函数setter和getter

​ ● 面向对象中的变量

​ ● 构造函数

​ ● 抽象方法、抽象类和接口

​ ● 类函数

​ ● 总结

img

第十章 Dart语法篇之面向对象继承和Mixins(六**)**

​ ● 简述

​ ● 类的单继承

​ ● 基于Mixins的多继承

​ ● 总结

img

第十一章 Dart语法篇之类型系统与泛型(七)

​ ● 简述

​ ● 可选类型

​ ● 接口类型

​ ● 泛型

​ ● 类型具体化

​ ● 总结

img

第十二章 Flutter中的widget

​ ● Flutter页面-基础Widget

​ ● Widget

​ ● StatelessWidget

​ ● State生命周期

​ ● 基础widget

​ ● DefaultTextStyle

​ ● FlutterLogo

​ ● Icon

​ ● Iamge.asset

​ ● CircleAvatar

​ ● FadeInImage

​ ● 按钮

​ ● FlatButton

​ ● OutlineButton

​ ● TextFormField

img

由于文章内容比较多,篇幅有限,资料已经被整理成了PDF文档,有需要 Flutter技术解析与实战 完整文档的可扫描下方卡片免费获取!

《Flutter入门与实战》

目录

img

img

img

img

第一章、Flutter基本功能

​ ● 我的第一个 Flutter 应用之旅

​ ● 容器的盒子模型

​ ● 构建一个常用的页面框架

​ ● 设置 App 的主色调与字体

​ ● 来一个图文并茂的列表

​ ● 给列表增加下拉刷新和上滑加载更多功能

​ ● 使用cached_network_image 优化图片加载体验

​ ● 仿一个微信价值几个亿的页面

​ ● 开发一个常用的登录页面

​ ● 封装一个通用的文本输入框

​ ● 底部弹窗ModelBottomSheet详解

​ ● 利用CustomScrollView实现更有趣的滑动效果

​ ● 底部弹窗如何实现多项选择?

img

第二章、Flutter路由管理

​ ● App页面路由及路由拦截实现

​ ● 路由参数处理

​ ● 初识 fluro 路由管理

​ ● 使用 fluro 的转场动画提高页面切换体验

​ ● 使用自定义转场动画实现个性化页面切换

​ ● 此路是我开,此树是我栽。若是没权限,403到来

​ ● Flutter 2.0的路由把我搞蒙了

​ ● 山路十八弯的2.0路由

img

第三章、Flutter网络请求插件Dio

​ ● 初次见面,网络请求王者之dio

​ ● 利用 Dio请求删除数据

​ ● 使用 Dio的 Patch请求完成详情编辑

​ ● 使用 Post 请求增加动态

​ ● 一文搞定图片选择及图片上传

​ ● 使用 GetIt 同步不同页面间数据

​ ● Dio 封装之金屋藏娇

​ ● Dio 之拦截器

​ ● Dio之戛然而止

​ ● 从源码深入了解Dio 的

​ ● 小伙子,你买票了吗?

​ ● 手写一个持久化的

​ ● Dio之文件下载

​ ● Dio 篇章总结

img

第四章、Flutter状态管理

​ ● 基础原理篇

​ ● Provider篇

​ ● Redux篇

​ ● Mobx篇

​ ● Getx篇

​ ● BLOC篇

​ ● 状态管理系列大汇总

img

第五章、Flutter 动画

​ ● 使用 Animation 构建爱心三连动画

​ ● 让你的组件拥有三维动效

​ ● 小姐姐渐现效果 ——AnimatedOpacity 使用

​ ● 使用 AnimatedBuilder分离组件和动画,实现动效复用

​ ● 看这一颗跳动的热心—— AnimatedPadding 应用

​ ● 使用AnimatedSwitcher 做场景切换

​ ● 给小姐姐的照片调个颜色滤镜

img

由于文章内容比较多,篇幅有限,资料已经被整理成了PDF文档,有需要 Flutter技术解析与实战 完整文档的可扫描下方卡片免费获取!

# 《Flutter完整开发实战详解》

目录

img

第一章 Dart语言和Flutter基础

img

第二章 快速开发实战篇

img

第三章 打包与填坑篇

img

第四章 Redux、主题、国际化

img

第五章 深入探索

img

第六章 深入Widget原理

img

第七章 深入布局原理

img

第八章 实用技巧与填坑

img

第九章 深入绘制原理

img

第十章 深入图片加载流程

img

第十一章 全面深入理解Stream

img

第十二章 全面深入理解状态管理设计

img

第十三章 全面深入触摸和滑动原理

img

第十四章 混合开发打包 Android 篇

l Flutter 面试知识点集锦

l Flutter 开发实战与前景展望 - RTC Dev Meetup

img

由于文章内容比较多,篇幅有限,资料已经被整理成了PDF文档,有需要 Flutter技术解析与实战 完整文档的可扫描下方卡片免费获取!

**更有更多资料,加微信免费领取**

img

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值