lottie是airbnb推出的一个直接将AE工程转化为动画的工具。
ae.project-->data.json-->LottieComposition-->Lottie动画
之前做一个比较复杂的动画,花了两天时间都在画各种弧,计算运动轨迹等等。感觉我不是在编程,我是在算数学。
上lottie的过程,花了半天时间调AE动画,因为设计师的电脑上装插件没装成功。所以AE转json文件的过程都抛给了开发。
原本做第一个动画就花了2天,现在4个动画,我几分钟全搞定了。设计想怎么改,就怎么改,我无非是替换一下json文件就可以了,真是痛快。在设计眼皮下,一像素一像素调UI,我觉得是最浪费时间的事。
说说碰到的这个问题吧:
场景:第一打开Activity的时候,动画过了0.3s才显示出来,好点的手机不会,老点的手机就比较明显。
分析了一下源码
public void setAnimation(@RawRes final int animationResId, final CacheStrategy cacheStrategy) {
this.animationResId = animationResId;
animationName = null;
if (RAW_RES_WEAK_REF_CACHE.indexOfKey(animationResId) > 0) {
WeakReference compRef = RAW_RES_WEAK_REF_CACHE.get(animationResId);
LottieComposition ref = compRef.get();
if (ref != null) {
setComposition(ref);
return;
}
} else if (RAW_RES_STRONG_REF_CACHE.indexOfKey(animationResId) > 0) {
setComposition(RAW_RES_STRONG_REF_CACHE.get(animationResId));
return;
}
clearComposition();
cancelLoaderTask();
compositionLoader = LottieComposition.Factory.fromRawFile(getContext(), animationResId,
new OnCompositionLoadedListener() {
@Override public void onCompositionLoaded(LottieComposition composition) {
if (cacheStrategy == CacheStrategy.Strong) {
RAW_RES_STRONG_REF_CACHE.put(animationResId, composition);
} else if (cacheStrategy == CacheStrategy.Weak) {
RAW_RES_WEAK_REF_CACHE.put(animationResId, new WeakReference<>(composition));
}
setComposition(composition);
}
});
}
setAnimation的过程,会先从cache中取,如果没有就自己构造一个Composition,composition中包含了所有的动画描述信息。
所以问题就出在了composition的构造
/**
* Loads a composition from a json reader.
*
* ex: fromInputStream(context, new FileInputStream(filePath), (composition) -> {});
*/
public static Cancellable fromJsonReader(
JsonReader reader, OnCompositionLoadedListener listener) {
AsyncCompositionLoader loader = new AsyncCompositionLoader(listener);
loader.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, reader);
return loader;
}
不断跟进LottieComposition.Factory中的fromRawFile()方法,最终发现AsyncCompositionLoader,问题就出来了,从ae产物json动画描述文件的解析过程是一个异步的过程,自然会影响到动画的第一打开的速度。
对于起步时间敏感的动画,有没有同步的方法给我们调一调呢?
搜了下sync关键字,果然有。
public static LottieComposition fromJsonSync(JsonReader reader) throws IOException {
return LottieCompositionParser.parse(reader);
}
然后我们再倒着找最外层封装好的方法:
/**
* Loads a composition from a file stored in /assets.
*/
public static Cancellable fromAssetFileName(
Context context, String fileName, OnCompositionLoadedListener listener) {
InputStream stream;
try {
stream = context.getAssets().open(fileName);
} catch (IOException e) {
throw new IllegalArgumentException("Unable to find file " + fileName, e);
}
return fromInputStream(stream, listener);
}
可以可以,就是这个了,把原来xml中的data.json复制一份放在asset目录下,
LottieAnimationView lottieAnimationView = findViewById(R.id.animation_view);
LottieComposition composition = LottieComposition.Factory.fromFileSync(this,"data.json");
lottieAnimationView.setComposition(composition);
运行一下,OK,延迟消失了。
当然异步加载有异步的好处。大家可以根据自己的需要来选择同步异步,或者是否需要CacheStrategy来做强缓存,或者弱缓存,提高加载的速度。