深入理解Flutter动画原理

final TickerCallback _onTick;

}

将AnimationControllerd对象中的_tick()方法,赋值给Ticker对象的_onTick成员变量,再来看看该_tick方法。

2.1.3 _internalSetValue

[-> lib/src/animation/animation_controller.dart ::AnimationController]

void _internalSetValue(double newValue) {

_value = newValue.clamp(lowerBound, upperBound);

if (_value == lowerBound) {

_status = AnimationStatus.dismissed;

} else if (_value == upperBound) {

_status = AnimationStatus.completed;

} else {

_status = (_direction == _AnimationDirection.forward) ?

AnimationStatus.forward :

AnimationStatus.reverse;

}

}

根据当前的value值来初始化动画状态_status

2.2 forward

[-> lib/src/animation/animation_controller.dart ::AnimationController]

TickerFuture forward({ double from }) {

//默认采用向前的动画方向

_direction = _AnimationDirection.forward;

if (from != null)

value = from;

return _animateToInternal(upperBound); //[见小节2.3]

}

_AnimationDirection是枚举类型,有forward(向前)和reverse(向后)两个值,也就是说该方法的功能是指从from开始向前滑动,

2.3 _animateToInternal

[-> lib/src/animation/animation_controller.dart ::AnimationController]

TickerFuture _animateToInternal(double target, { Duration duration, Curve curve = Curves.linear }) {

double scale = 1.0;

if (SemanticsBinding.instance.disableAnimations) {

switch (animationBehavior) {

case AnimationBehavior.normal:

scale = 0.05;

break;

case AnimationBehavior.preserve:

break;

}

}

Duration simulationDuration = duration;

if (simulationDuration == null) {

final double range = upperBound - lowerBound;

final double remainingFraction = range.isFinite ? (target - _value).abs() / range : 1.0;

//根据剩余动画的百分比来评估仿真动画剩余时长

simulationDuration = this.duration * remainingFraction;

} else if (target == value) {

//已到达动画终点,不再执行动画

simulationDuration = Duration.zero;

}

//停止老的动画[见小节2.3.1]

stop();

if (simulationDuration == Duration.zero) {

if (value != target) {

_value = target.clamp(lowerBound, upperBound);

notifyListeners();

}

_status = (_direction == _AnimationDirection.forward) ?

AnimationStatus.completed :

AnimationStatus.dismissed;

_checkStatusChanged();

//当动画执行时间已到,则直接结束

return TickerFuture.complete();

}

//[见小节2.4]

return _startSimulation(_InterpolationSimulation(_value, target, simulationDuration, curve, scale));

}

默认采用的是线性动画曲线Curves.linear。

2.3.1 AnimationController.stop

void stop({ bool canceled = true }) {

_simulation = null;

_lastElapsedDuration = null;

//[见小节2.3.2]

_ticker.stop(canceled: canceled);

}

2.3.2 Ticker.stop

[-> lib/src/scheduler/ticker.dart]

void stop({ bool canceled = false }) {

if (!isActive) //已经不活跃,则直接返回

return;

final TickerFuture localFuture = _future;

_future = null;

_startTime = null;

//[见小节2.3.3]

unscheduleTick();

if (canceled) {

localFuture._cancel(this);

} else {

localFuture._complete();

}

}

2.3.3 Ticker.unscheduleTick

[-> lib/src/scheduler/ticker.dart]

void unscheduleTick() {

if (scheduled) {

SchedulerBinding.instance.cancelFrameCallbackWithId(_animationId);

_animationId = null;

}

}

2.3.4 _InterpolationSimulation初始化

[-> lib/src/animation/animation_controller.dart ::_InterpolationSimulation]

class _InterpolationSimulation extends Simulation {

_InterpolationSimulation(this._begin, this._end, Duration duration, this._curve, double scale)
_durationInSeconds = (duration.inMicroseconds * scale) / Duration.microsecondsPerSecond;

final double _durationInSeconds;

final double _begin;

final double _end;

final Curve _curve;

}

该方法创建插值模拟器对象,并初始化起点、终点、动画曲线以及时长。这里用的Curve是线性模型,也就是说采用的是匀速运动。

2.4 _startSimulation

[-> lib/src/animation/animation_controller.dart]

TickerFuture _startSimulation(Simulation simulation) {

_simulation = simulation;

_lastElapsedDuration = Duration.zero;

_value = simulation.x(0.0).clamp(lowerBound, upperBound);

//[见小节2.5]

final TickerFuture result = _ticker.start();

_status = (_direction == _AnimationDirection.forward) ?

AnimationStatus.forward :

AnimationStatus.reverse;

//[见小节2.4.1]

_checkStatusChanged();

return result;

}

2.4.1 _checkStatusChanged

[-> lib/src/animation/animation_controller.dart]

void _checkStatusChanged() {

final AnimationStatus newStatus = status;

if (_lastReportedStatus != newStatus) {

_lastReportedStatus = newStatus;

notifyStatusListeners(newStatus); //通知状态改变

}

}

这里会回调_statusListeners中的所有状态监听器,这里的状态就是指AnimationStatus的dismissed、forward、reverse以及completed。

2.5 Ticker.start

[-> lib/src/scheduler/ticker.dart]

TickerFuture start() {

future = TickerFuture.();

if (shouldScheduleTick) {

scheduleTick(); //[见小节2.6]

}

if (SchedulerBinding.instance.schedulerPhase.index > SchedulerPhase.idle.index &&

SchedulerBinding.instance.schedulerPhase.index < SchedulerPhase.postFrameCallbacks.index)

_startTime = SchedulerBinding.instance.currentFrameTimeStamp;

return _future;

}

此处的shouldScheduleTick等于!muted && isActive && !scheduled,也就是没有调度过的活跃状态才会调用Tick。

2.6 Ticker.scheduleTick

[-> lib/src/scheduler/ticker.dart]

void scheduleTick({ bool rescheduling = false }) {

//[见小节2.7]

_animationId = SchedulerBinding.instance.scheduleFrameCallback(_tick, rescheduling: rescheduling);

}

此处的_tick会在下一次vysnc触发时回调执行,见小节2.10。

2.7 scheduleFrameCallback

[-> lib/src/scheduler/binding.dart]

int scheduleFrameCallback(FrameCallback callback, { bool rescheduling = false }) {

//[见小节2.8]

scheduleFrame();

_nextFrameCallbackId += 1;

_transientCallbacks[_nextFrameCallbackId] = _FrameCallbackEntry(callback, rescheduling: rescheduling);

return _nextFrameCallbackId;

}

将前面传递过来的Ticker._tick()方法保存在_FrameCallbackEntry的callback中,然后将_FrameCallbackEntry记录在Map类型的_transientCallbacks,

2.8 scheduleFrame

[-> lib/src/scheduler/binding.dart]

void scheduleFrame() {

if (_hasScheduledFrame || !_framesEnabled)

return;

ui.window.scheduleFrame();

_hasScheduledFrame = true;

}

从文章Flutter之setState更新机制,可知此处调用的ui.window.scheduleFrame(),会注册vsync监听。当当下一次vsync信号的到来时会执行handleBeginFrame()。

2.9 handleBeginFrame

[-> lib/src/scheduler/binding.dart:: SchedulerBinding]

void handleBeginFrame(Duration rawTimeStamp) {

Timeline.startSync(‘Frame’, arguments: timelineWhitelistArguments);

_firstRawTimeStampInEpoch ??= rawTimeStamp;

_currentFrameTimeStamp = _adjustForEpoch(rawTimeStamp ?? _lastRawTimeStamp);

if (rawTimeStamp != null)

_lastRawTimeStamp = rawTimeStamp;

//此时阶段等于SchedulerPhase.idle;

_hasScheduledFrame = false;

try {

Timeline.startSync(‘Animate’, arguments: timelineWhitelistArguments);

_schedulerPhase = SchedulerPhase.transientCallbacks;

//执行动画的回调方法

final Map<int, _FrameCallbackEntry> callbacks = _transientCallbacks;

_transientCallbacks = <int, _FrameCallbackEntry>{};

callbacks.forEach((int id, _FrameCallbackEntry callbackEntry) {

if (!_removedIds.contains(id))

_invokeFrameCallback(callbackEntry.callback, _currentFrameTimeStamp, callbackEntry.debugStack);

});

_removedIds.clear();

} finally {

_schedulerPhase = SchedulerPhase.midFrameMicrotasks;

}

}

该方法主要功能是遍历_transientCallbacks,从前面小节[2.7],可知该过程会执行Ticker._tick()方法。

2.10 Ticker._tick

[-> lib/src/scheduler/ticker.dart]

void _tick(Duration timeStamp) {

_animationId = null;

_startTime ??= timeStamp;

//[见小节2.11]

_onTick(timeStamp - _startTime);

//根据活跃状态来决定是否再次调度

if (shouldScheduleTick)

scheduleTick(rescheduling: true);

}

该方法主要功能:

  • 小节[2.1.2]的Ticker初始化中,可知此处_onTick便是AnimationController的_tick()方法;

  • 小节[2.5]已介绍当仍处于活跃状态,则会再次调度,回到小节[2.6]的scheduleTick(),从而形成动画的连续绘制过程。

2.11 AnimationController._tick

[-> lib/src/animation/animation_controller.dart]

void _tick(Duration elapsed) {

_lastElapsedDuration = elapsed;

//获取已过去的时长

final double elapsedInSeconds = elapsed.inMicroseconds.toDouble() / Duration.microsecondsPerSecond;

_value = _simulation.x(elapsedInSeconds).clamp(lowerBound, upperBound);

if (_simulation.isDone(elapsedInSeconds)) {

_status = (_direction == _AnimationDirection.forward) ?

AnimationStatus.completed :

AnimationStatus.dismissed;

stop(canceled: false); //当动画已完成,则停止

}

notifyListeners(); //通知监听器[见小节2.11.1]

_checkStatusChanged(); //通知状态监听器[见小节2.11.2]

}

2.11.1 notifyListeners

[-> lib/src/animation/listener_helpers.dart ::AnimationLocalListenersMixin]

void notifyListeners() {

final List localListeners = List.from(_listeners);

for (VoidCallback listener in localListeners) {

try {

if (_listeners.contains(listener))

listener();

} catch (exception, stack) {

}

}

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

下图是我进阶学习所积累的历年腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节

整理不易,望各位看官老爷点个关注转发,谢谢!祝大家都能得到自己心仪工作。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

79475852)]

[外链图片转存中…(img-A6yXzJQ9-1713679475853)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

下图是我进阶学习所积累的历年腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节

[外链图片转存中…(img-jDjKxm16-1713679475854)]

整理不易,望各位看官老爷点个关注转发,谢谢!祝大家都能得到自己心仪工作。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter是一种用于构建跨平台移动应用程序的开源UI工具包。它使用Dart编程语言,并提供了一个丰富的组件库,使开发人员可以轻松地构建漂亮、流畅且高性能的应用程序。Flutter的实现原理涉及几个关键概念和流程。 首先,Flutter应用程序由一个个小部件(widget)构成。小部件是构建用户界面的基本元素,可以是按钮、文本框、图像等。小部件可以嵌套,并按照一定的层次结构组织在一起,形成复杂的用户界面。 其次,Flutter使用Skia图形引擎来绘制用户界面。Skia是一个跨平台的2D图形库,它提供了高效的绘图和渲染功能。Flutter将应用程序界面转化为一系列的绘图指令,然后通过Skia将这些指令渲染到屏幕上。 另外,Flutter应用程序是通过Dart虚拟机来执行的。Dart虚拟机负责解释和执行Dart代码,并管理应用程序的运行时环境。Flutter框架提供了丰富的API和工具,使开发人员可以轻松地编写和调试应用程序。 在具体的实现过程中,Flutter应用程序通常包含一个或多个FlutterActivity。FlutterActivity是一个Android Activity,它负责创建和管理Flutter的运行时环境。在FlutterActivity中,通过FlutterActivityDelegate处理核心流程,包括创建FlutterView或FlutterNativeView,并将其设置为应用程序的主视图。 总之,Flutter通过组件化的方式构建用户界面,使用Skia图形引擎渲染界面,并由Dart虚拟机执行应用程序。这种架构使得Flutter具有高性能、快速开发和良好的跨平台兼容性的特点。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值