export default class Test extends Component {
state = {
bounceValue: new Animated.Value(0),
};
render() {
return (
<Animated.Image source={require(‘./my-icon.png’)} style={{
transform: [{scale: this.state.bounceValue}]
}}/>)
}
componentDidMount() {
Animated.timing(this.state.bounceValue, {
toValue: 3,
duration: 3000,
// useNativeDriver: true 这里先注释掉,标记为注释@1
}).start()
}
}
通过查看AnimatedImplementation.js文件可以查看到动画源码,篇幅有限仅展示核心代码
所有Animated的js源码都在AnimatedImplementation.js中,本文RN版本为0.57.8.
首先看下动画的入口函数:Animated.timing
该函数定义在181行,不同RN版本对应的行数不一致,请以自己的版本为准。
const timing = function(
value: AnimatedValue | AnimatedValueXY,
config: TimingAnimationConfig,
): CompositeAnimation {
const start = function(
animatedValue: AnimatedValue | AnimatedValueXY,
configuration: TimingAnimationConfig,
callback?: ?EndCallback,
): void {
callback = _combineCallbacks(callback, configuration);
const singleValue: any = animatedValue;
const singleConfig: any = configuration;
singleValue.stopTracking();
if (configuration.toValue instanceof AnimatedNode) {
singleValue.track(
new AnimatedTracking(
singleValue,
configuration.toValue,
TimingAnimation,
singleConfig,
callback,
),
);
} else {
singleValue.animate(new TimingAnimation(singleConfig), callback);
}
};
这里的singleValue是传入的第一个参数this.state.bounceValue,为AnimatedValue类型。
这里的singleConfig是传入的第二个参数。
首先分析下第一个参数的AnimatedValue这个类型的animate方法:
animate(animation: Animation, callback: ?EndCallback): void {
let handle = null;
if (animation.__isInteraction) {
handle = InteractionManager.createInteractionHandle();
}
const previousAnimation = this._animation;
this._animation && this._animation.stop();
this._animation = animation;
animation.start(
this._value,
value => {
// Natively driven animations will never call into that callback, therefore we can always
// pass flush = true to allow the updated value to propagate to native with setNativeProps
this._updateValue(value, true /* flush */);
},
result => {
this._animation = null;
if (handle !== null) {
InteractionManager.clearInteractionHandle(handle);
}
callback && callback(result);
},
previousAnimation,
this,
);
}
该方法内部主要是为了调用传入参数animation的start方法,这个参数就是上面传过来的new TimingAnimation(singleConfig)对象。TimingAnimation的start方法如下:
start(
fromValue: number,
onUpdate: (value: number) => void,
onEnd: ?EndCallback,
previousAnimation: ?Animation,
animatedValue: AnimatedValue,
): void {
this.__active = true;
this._fromValue = fromValue;
this._onUpdate = onUpdate;
this.__onEnd = onEnd;
const start = () => {
// Animations that sometimes have 0 duration and sometimes do not
// still need to use the native driver when duration is 0 so as to
// not cause intermixed JS and native animations.
if (this._duration === 0 && !this._useNativeDriver) {
this._onUpdate(this._toValue);
this.__debouncedOnEnd({finished: true});
} else {
this._startTime = Date.now();
if (this._useNativeDriver) {
this.__startNativeAnimation(animatedValue);
} else {
this._animationFrame = requestAnimationFrame(
this.onUpdate.bind(this),
);
}
}
};
if (this._delay) {
this._timeout = setTimeout(start, this._delay);
} else {
start();
}
}
这里出现了分支,当注释@1打开时,_useNativeDriver为true,动画的执行方式将交由原生端,不再走下边的js端。
原生端实现:
可以看到js调用了__startNativeAnimation方法,我们看下__startNativeAnimation
__startNativeAnimation(animatedValue: AnimatedValue): void {
animatedValue.__makeNative();
this.__nativeId = NativeAnimatedHelper.generateNewAnimationId();
NativeAnimatedHelper.API.startAnimatingNode(
this.__nativeId,
animatedValue.__getNativeTag(),
this.__getNativeAnimationConfig(),
this.__debouncedOnEnd.bind(this),
);
}
我们着重看下这个方法NativeAnimatedHelper.API.startAnimatingNode:
startAnimatingNode: function(
animationId: ?number,
nodeTag: ?number,
config: Object,
endCallback: EndCallback,
): void {
assertNativeAnimatedModule();
NativeAnimatedModule.startAnimatingNode(
animationId,
nodeTag,
config,
endCallback,
);
},
我们可以看到内部执行了NativeAnimatedModule.startAnimatingNode,熟悉Android开发的同学可能知道这是调用了Android端的方法,那我们去Android端看下这个NativeAnimatedModule
这里边包含了Android与JS动画交互的方法,有兴趣的同学可以看下这个文件,该文件在这个包下
package com.facebook.react.animated;
我们看下startAnimatingNode方法:
@ReactMethod
public void startAnimatingNode(
final int animationId,
final int animatedNodeTag,
final ReadableMap animationConfig,
final Callback endCallback) {
mOperations.add(new UIThreadOperation() {
@Override
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
[外链图片转存中…(img-TIIhwUh3-1715830651695)]
[外链图片转存中…(img-mHqsAh76-1715830651697)]
[外链图片转存中…(img-nHWLsVeX-1715830651700)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!