lottie載入動畫,第一次有延遲問題
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<LottieComposition> 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. * <p> * 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來做強快取,或者弱快取,提高載入的速度。