diff --git a/README.md b/README.md index 6835e2b086e36f0b7a695a64e01cc03dd013be02..914c5e1d3c3010966994a71fa4bbb0690280f4e2 100644 --- a/README.md +++ b/README.md @@ -55,5 +55,5 @@ where string is the url path to the json file to be loaded. ``` dependencies { implementation fileTree(dir: 'libs', include: ['*.har']) - implementation 'io.openharmony.tpc.thirdlib:lottie-ohos:1.0.7' + implementation 'io.openharmony.tpc.thirdlib:lottie-ohos:1.0.8' } \ No newline at end of file diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java index 842a2c3a89374b8f53507b14311479911f7a1ed5..8fd3cb2fed2b2959dc7866d5f86857af4b9b0dba 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieAnimationView.java @@ -1,7 +1,6 @@ package com.airbnb.lottie; import com.airbnb.lottie.model.KeyPath; -import com.airbnb.lottie.parser.moshi.JsonReader; import com.airbnb.lottie.utils.ContextUtil; import com.airbnb.lottie.utils.HMOSLogUtil; import com.airbnb.lottie.value.SimpleLottieValueCallback; @@ -1038,7 +1037,7 @@ public class LottieAnimationView extends Image implements Component.BindStateCha //TODO : scaleType FitXY mode is not supported in HMOS /** - * Disable the extraScale mode in {@link #drawToCanvas(Canvas)} function when scaleType is FitXY. It doesn't affect the rendering with other scaleTypes. + * Disable the extraScale mode in {@link LottieDrawable#drawToCanvas(Canvas)} function when scaleType is FitXY. It doesn't affect the rendering with other scaleTypes. * *

When there are 2 animation layout side by side, the default extra scale mode might leave 1 pixel not drawn between 2 animation, and * disabling the extraScale mode can fix this problem

@@ -1046,7 +1045,7 @@ public class LottieAnimationView extends Image implements Component.BindStateCha * Attention: Disable the extra scale mode can downgrade the performance and may lead to larger memory footprint. Please only disable this * mode when using animation with a reasonable dimension (smaller than screen size). * - * @see LottieDrawable#drawWithNewAspectRatio(Canvas) + * @see LottieDrawable drawWithNewAspectRatio(Canvas) */ /*public void disableExtraScaleModeInFitXY() { lottieHMOSDrawable.disableExtraScaleModeInFitXY(); diff --git a/lottie/src/main/java/com/airbnb/lottie/utils/InvalidationHandler.java b/lottie/src/main/java/com/airbnb/lottie/utils/InvalidationHandler.java new file mode 100644 index 0000000000000000000000000000000000000000..1a8c16f395c5749521068c142b41e6beceb78ff8 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/utils/InvalidationHandler.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.airbnb.lottie.utils; + +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.eventhandler.InnerEvent; + +import java.lang.ref.WeakReference; + +/** + * 功能描述 + */ +class InvalidationHandler extends EventHandler { + static final int MSG_TYPE_INVALIDATION = -1; + + private final WeakReference mLottieRef; + + InvalidationHandler(final LottieValueAnimator gifDrawable) { + super(EventRunner.getMainEventRunner()); + mLottieRef = new WeakReference<>(gifDrawable); + } + + @Override + protected void processEvent(InnerEvent event) { + final LottieValueAnimator ltDrawable = mLottieRef.get(); + if (ltDrawable == null) { + return; + } + if (event.eventId == MSG_TYPE_INVALIDATION) { + ltDrawable.doFrame(System.nanoTime()); + } + } +} diff --git a/lottie/src/main/java/com/airbnb/lottie/utils/LottieDelayExecutor.java b/lottie/src/main/java/com/airbnb/lottie/utils/LottieDelayExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..20d8991ea5f77c64029879b6e4323c517a0b1094 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/utils/LottieDelayExecutor.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.airbnb.lottie.utils; + +import java.util.concurrent.ScheduledThreadPoolExecutor; + +final class LottieDelayExecutor extends ScheduledThreadPoolExecutor { + private static final int CORE_POOL_SIZE = 1; + + private LottieDelayExecutor() { + super(CORE_POOL_SIZE, new DiscardPolicy()); + } + + // Lazy initialization via inner-class holder + private static final class InstanceHolder { + private static final LottieDelayExecutor INSTANCE = new LottieDelayExecutor(); + } + + static LottieDelayExecutor getInstance() { + return InstanceHolder.INSTANCE; + } +} diff --git a/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java b/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java index 3884cf9859bed67e1a8b97ddf45a212820e79890..76e9526e8a23e45fe1f8b34e79048e737fdf3ed3 100644 --- a/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java +++ b/lottie/src/main/java/com/airbnb/lottie/utils/LottieValueAnimator.java @@ -4,16 +4,20 @@ import com.airbnb.lottie.LottieComposition; import ohos.agp.animation.AnimatorValue; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; /** * This is a slightly modified {@link AnimatorValue} that allows us to update start and end values * easily optimizing for the fact that we know that it's a value animator with 2 floats. */ -public class LottieValueAnimator extends BaseLottieAnimator implements InvocationHandler { +public class LottieValueAnimator extends BaseLottieAnimator { + private static final long EXCEEDS_TIME_SINCE_FRAME = 280000000; + + private static final long AVERAGE_TIME_SINCE_FRAME = 180000000; + + private static final long FRAME_TIME_INTERVAL = 16L; private float speed = 1f; @@ -33,28 +37,15 @@ public class LottieValueAnimator extends BaseLottieAnimator implements Invocatio protected boolean running = false; - private Class choreographerClass; - - private Class frameCallbackClass; - - private Object callbackProxy; - - private Object choreographerObject; - public LottieValueAnimator() { - try { - choreographerClass = Class.forName("android.view.Choreographer"); - frameCallbackClass = Class.forName("android.view.Choreographer$FrameCallback"); - callbackProxy = Proxy.newProxyInstance(frameCallbackClass.getClass().getClassLoader(), - new Class[]{frameCallbackClass}, this); - Method getInstanceMethod = choreographerClass.getMethod("getInstance", (Class[]) null); - choreographerObject = getInstanceMethod.invoke(null); - } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | - InvocationTargetException e) { - e.printStackTrace(); - } + mInvalidationHandler = new InvalidationHandler(this); } + private final RenderTask mRenderTask = new RenderTask(this); + final ScheduledThreadPoolExecutor mExecutor = LottieDelayExecutor.getInstance(); + ScheduledFuture mRenderTaskSchedule; + final InvalidationHandler mInvalidationHandler; + /** * Returns a float representing the current value of the animation from 0 to 1 * regardless of the animation speed, direction, or min and max frames. @@ -112,15 +103,6 @@ public class LottieValueAnimator extends BaseLottieAnimator implements Invocatio return running; } - @Override - public Object invoke(Object o, Method method, Object[] objects) throws Throwable { - if (objects != null && objects.length > 0) { - long frameTimeNanos = (long) objects[0]; - this.doFrame(frameTimeNanos); - } - return null; - } - public void doFrame(long frameTimeNanos) { postFrameCallback(); if (composition == null || !isRunning()) { @@ -128,6 +110,9 @@ public class LottieValueAnimator extends BaseLottieAnimator implements Invocatio } //HiTraceId traceid = L.beginSection("LottieValueAnimator#doFrame"); long timeSinceFrame = lastFrameTimeNs == 0 ? 0 : frameTimeNanos - lastFrameTimeNs; + if (timeSinceFrame > EXCEEDS_TIME_SINCE_FRAME) { + timeSinceFrame = AVERAGE_TIME_SINCE_FRAME; + } float frameDuration = getFrameDurationNs(); float dFrames = timeSinceFrame / frameDuration; @@ -319,13 +304,7 @@ public class LottieValueAnimator extends BaseLottieAnimator implements Invocatio protected void postFrameCallback() { if (isRunning()) { removeFrameCallback(false); - try { - Method postFrameMethod = choreographerClass.getDeclaredMethod("postFrameCallback", - new Class[]{frameCallbackClass}); - postFrameMethod.invoke(choreographerObject, new Object[]{callbackProxy}); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } + mRenderTaskSchedule = mExecutor.schedule(mRenderTask, FRAME_TIME_INTERVAL, TimeUnit.MILLISECONDS); } } @@ -336,13 +315,7 @@ public class LottieValueAnimator extends BaseLottieAnimator implements Invocatio //MainThread protected void removeFrameCallback(boolean stopRunning) { - try { - Method removeFrameMethod = choreographerClass.getDeclaredMethod("removeFrameCallback", - new Class[]{frameCallbackClass}); - removeFrameMethod.invoke(choreographerObject, new Object[]{callbackProxy}); - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } + mExecutor.remove(mRenderTask); if (stopRunning) { running = false; } diff --git a/lottie/src/main/java/com/airbnb/lottie/utils/RenderTask.java b/lottie/src/main/java/com/airbnb/lottie/utils/RenderTask.java new file mode 100644 index 0000000000000000000000000000000000000000..8e3476afda7feb74795ecb94b2e5ac26d95485b4 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/utils/RenderTask.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.airbnb.lottie.utils; + + +class RenderTask extends SafeRunnable { + + RenderTask(LottieValueAnimator ltAnimator) { + super(ltAnimator); + } + + @Override + public void doFrame() { + lt.mInvalidationHandler.sendEvent(InvalidationHandler.MSG_TYPE_INVALIDATION, 0); + } +} diff --git a/lottie/src/main/java/com/airbnb/lottie/utils/SafeRunnable.java b/lottie/src/main/java/com/airbnb/lottie/utils/SafeRunnable.java new file mode 100644 index 0000000000000000000000000000000000000000..ee20dd1ca5ae634ca000858cca79fafd3efd75c8 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/utils/SafeRunnable.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.airbnb.lottie.utils; + +/** + * 功能描述 + */ +abstract class SafeRunnable implements Runnable { + + LottieValueAnimator lt; + SafeRunnable( LottieValueAnimator ltAnimator) { + lt = ltAnimator; + } + + @Override + public final void run() { + try { + doFrame(); + } catch (Throwable throwable) { + final Thread.UncaughtExceptionHandler uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler(); + if (uncaughtExceptionHandler != null) { + uncaughtExceptionHandler.uncaughtException(Thread.currentThread(), throwable); + } + throw throwable; + } + } + + abstract void doFrame(); +}