Flutter 119: 图解简易 ACEFrameAnimated 帧动画

简介: 0 基础学习 Flutter,第一百一十九步:尝试简单帧动画效果!

    小菜在做 Android 开发时,常常需要 帧动画 来作为作为 loading 动画;而 Flutter 没有直接提供类似于 帧动画 的组件,小菜简单尝试一个简单的 ACEFrameAnimated 帧动画小组件;

    小菜理解的 帧动画 其实一系列图片在一段时间内的叠加展示,以达到连贯的动画效果;

ACEFrameAnimated

    小菜认为,帧动画最重要的两个元素,分别是图片资源和间隔时间;之后便可对图片根据间隔时间来循环展示;为了适配网络图片和本地图片,小菜设置了一个 ACEFramePicType 资源类型;

enum ACEFramePicType { asset, network }

final List<Map<ACEFramePicType, String>> picList;
final Duration duration;

ACEFrameAnimated(this.picList, this.duration);

    小菜计划返回一个基本的 Widget,并通过 Future 延迟加载图片资源,其中需要注意的是循环加载,注意当前数组下标;其中在 initState() 中更新图片 _framePicList() 时,需要在 Future.delayed 之前先加载第一张图片,否则会出现短暂空白的情况;

class _ACEFrameAnimatedState extends State<ACEFrameAnimated> {
  List<Map<ACEFramePicType, String>> _picList;
  Duration _duration;
  int _index = 0;
  Widget _buildWid = Container();

  _ACEFrameAnimatedState(this._picList, this._duration);

  @override
  void initState() {
    super.initState();
    _framePicList();
  }

  @override
  Widget build(BuildContext context) => _buildWid;

  _framePicList() async {
    setState(() {
      _index = _index % _picList.length;
      _buildWid = Container(
          child: _picList[_index].keys.toList()[0] == ACEFramePicType.asset
              ? Image.asset(_picList[_index].values.toList()[0])
              : Image.network(_picList[_index].values.toList()[0]));
      _index++;
    });
    await Future.delayed(_duration, () => _framePicList());
  }
}

Tips

    小菜在退出页面时出现内存溢出,导致原因有两个,第一个是未清除 Widget 中的资源列表;第二个是 Future.delayed 发送消息后,await 导致消息未返回;

E/flutter (13298): This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback.
E/flutter (13298): The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.
E/flutter (13298): This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().
E/flutter (13298): #0      State.setState.<anonymous closure> (package:flutter/src/widgets/framework.dart:1112:9)
E/flutter (13298): #1      State.setState (package:flutter/src/widgets/framework.dart:1147:6)
E/flutter (13298): #2      _ACEFrameAnimatedState._framePicList (package:flutter_app/widget/ace_frame_animated.dart:32:5)
E/flutter (13298): #3      _ACEFrameAnimatedState._framePicList.<anonymous closure> (package:flutter_app/widget/ace_frame_animated.dart:40:43)
E/flutter (13298): #4      new Future.delayed.<anonymous closure> (dart:async/future.dart:316:39)
E/flutter (13298): #5      _rootRun (dart:async/zone.dart:1122:38)
E/flutter (13298): #6      _CustomZone.run (dart:async/zone.dart:1023:19)
E/flutter (13298): #7      _CustomZone.runGuarded (dart:async/zone.dart:925:7)
E/flutter (13298): #8      _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:965:23)
E/flutter (13298): #9      _rootRun (dart:async/zone.dart:1126:13)
E/flutter (13298): #10     _CustomZone.run (dart:async/zone.dart:1023:19)
E/flutter (13298): #11     _CustomZone.bindCallback.<anonymous closure> (dart:async/zone.dart:949:23)
E/flutter (13298): #12     Timer._createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:23:15)
E/flutter (13298): #13     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:384:19)
E/flutter (13298): #14     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:418:5)
E/flutter (13298): #15     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)

    小菜根据提示在使用 setState 时先判断当前 State 是否已绑定在 View 中;同时在 dispose 中清空资源;

@override
void dispose() {
  super.dispose();
  if (_picList != null) {
    _picList.clear();
  }
  if (widget != null && widget.picList != null) {
    widget.picList.clear();
  }
}

    ACEFrameAnimated 案例源码


    小菜仅实现了最基本的帧动画效果,对于效果的优化还未涉及;如有错误请多多指导!

来源: 阿策小和尚

目录
相关文章
|
4天前
|
缓存 监控 前端开发
【Flutter 前端技术开发专栏】Flutter 应用的启动优化策略
【4月更文挑战第30天】本文探讨了Flutter应用启动优化策略,包括理解启动过程、资源加载优化、减少初始化工作、界面布局简化、异步初始化、预加载关键数据、性能监控分析以及案例和未来优化方向。通过这些方法,可以缩短启动时间,提升用户体验。使用Flutter DevTools等工具可助于识别和解决性能瓶颈,实现持续优化。
【Flutter 前端技术开发专栏】Flutter 应用的启动优化策略
|
4天前
|
开发框架 Dart 前端开发
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
【4月更文挑战第30天】对比 Flutter(Dart,强类型,Google支持,快速热重载,高性能渲染)与 React Native(JavaScript,庞大生态,热重载,依赖原生渲染),文章讨论了开发语言、生态系统、性能、开发体验、学习曲线、社区支持及项目选择因素。两者各有优势,选择取决于项目需求、团队技能和长期维护考虑。参考文献包括官方文档和性能比较文章。
【Flutter前端技术开发专栏】Flutter与React Native的对比与选择
|
2天前
|
前端开发 C++ 容器
Flutter-完整开发实战详解(一、Dart-语言和-Flutter-基础)(1)
Flutter-完整开发实战详解(一、Dart-语言和-Flutter-基础)(1)
|
2天前
|
Android开发
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
Flutter完整开发实战详解(六、 深入Widget原理),2024百度Android岗面试真题收录解析
|
2天前
|
XML Dart Java
Flutter插件开发之APK自动安装,字节跳动Android岗面试题
Flutter插件开发之APK自动安装,字节跳动Android岗面试题
|
3天前
|
Java Android开发 设计模式
flutter音视频开发,Android开发需要学什么
flutter音视频开发,Android开发需要学什么
|
4天前
|
Dart 前端开发 测试技术
【Flutter前端技术开发专栏】Flutter开发中的代码质量与重构实践
【4月更文挑战第30天】随着Flutter在跨平台开发的普及,保证代码质量成为开发者关注的重点。优质代码能确保应用性能与稳定性,提高开发效率。关键策略包括遵循最佳实践,编写可读性强的代码,实施代码审查和自动化测试。重构实践在项目扩展时尤为重要,适时重构能优化结构,降低维护成本。开发者应重视代码质量和重构,以促进项目成功。
【Flutter前端技术开发专栏】Flutter开发中的代码质量与重构实践
|
4天前
|
存储 缓存 监控
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
【4月更文挑战第30天】本文探讨了Flutter中优化列表滚动性能的策略。建议使用`ListView.builder`以节省内存,避免一次性渲染所有列表项。为防止列表项重建,可使用`UniqueKey`或`ObjectKey`。缓存已渲染项、减少不必要的重绘和异步加载大数据集也是关键。此外,选择轻量级组件,如`StatelessWidget`,并利用Flutter DevTools监控性能以识别和解决瓶颈。持续测试和调整以提升用户体验。
【Flutter前端技术开发专栏】Flutter中的列表滚动性能优化
|
4天前
|
Dart 前端开发 安全
【Flutter前端技术开发专栏】Flutter中的线程与并发编程实践
【4月更文挑战第30天】本文探讨了Flutter中线程管理和并发编程的关键性,强调其对应用性能和用户体验的影响。Dart语言提供了`async`、`await`、`Stream`和`Future`等原生异步支持。Flutter采用事件驱动的单线程模型,通过`Isolate`实现线程隔离。实践中,可利用`async/await`、`StreamBuilder`和`Isolate`处理异步任务,同时注意线程安全和性能调优。参考文献包括Dart异步编程、Flutter线程模型和DevTools文档。
【Flutter前端技术开发专栏】Flutter中的线程与并发编程实践
|
4天前
|
Dart 前端开发 开发者
【Flutter前端技术开发专栏】Flutter中的性能分析工具Profiler
【4月更文挑战第30天】Flutter Profiler是用于性能优化的关键工具,提供CPU、GPU、内存和网络分析。它帮助开发者识别性能瓶颈,如CPU过度使用、渲染延迟、内存泄漏和网络效率低。通过实时监控和分析,开发者能优化代码、减少内存占用、改善渲染速度和网络请求,从而提升应用性能和用户体验。定期使用并结合实际场景与其它工具进行综合分析,是实现最佳实践的关键。
【Flutter前端技术开发专栏】Flutter中的性能分析工具Profiler