写点什么

深入理解 Flutter 动画原理,一个月成功收割腾讯、阿里、字节 offer

用户头像
Android架构
关注
发布于: 57 分钟前

@required TickerProvider vsync,


}) : _direction = _AnimationDirection.forward {


_ticker = vsync.createTicker(_tick); //[见小节 2.1.1]


_internalSetValue(value ?? lowerBound); //[见小节 2.1.3]


}


该方法说明:


  • AnimationController 初始化过程,一般都设置 duration 和 vsync 初值;

  • upperBound(上边界值)和 lowerBound(下边界值)都不能为空,且 upperBound 必须大于等于 lowerBound;

  • 创建默认的动画方向为向前(_AnimationDirection.forward);

  • 调用类型为 TickerProvider 的 vsync 对象的 createTicker()方法来创建 Ticker 对象;


TickerProvider 作为抽象类,主要的子类有 SingleTickerProviderStateMixin 和 TickerProviderStateMixin,这两个类的区别就是是否支持创建多个 TickerProvider,这里 SingleTickerProviderStateMixin 为例展开。

2.1.1 createTi

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


cker


[-> lib/src/widgets/ticker_provider.dart]


mixin SingleTickerProviderStateMixin<T extends StatefulWidget> on State<T> implements TickerProvider {


Ticker _ticker;


Ticker createTicker(TickerCallback onTick) {


//[见小节 2.1.2]


_ticker = Ticker(onTick, debugLabel: 'created by $this');


return _ticker;


}

2.1.2 Ticker 初始化

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


class Ticker {


Ticker(this._onTick, { this.debugLabel }) {


}


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;

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
深入理解Flutter动画原理,一个月成功收割腾讯、阿里、字节offer