提交 69aee752 编写于 作者: S Sam Judd

Make AnimationFactorys top level and add tests.

上级 34f797ba
package com.bumptech.glide.request.animation;
import android.graphics.drawable.Drawable;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.Mockito.mock;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE, emulateSdk = 18)
public class DrawableCrossFadeFactoryTest {
private DrawableCrossFadeFactory<Drawable> factory;
@SuppressWarnings("unchecked")
@Before
public void setUp() {
ViewAnimationFactory<Drawable> viewAnimationFactory = mock(ViewAnimationFactory.class);
factory = new DrawableCrossFadeFactory<Drawable>(viewAnimationFactory, 100 /*duration*/);
}
@Test
public void testReturnsNoAnimationIfFromMemoryCache() {
assertEquals(NoAnimation.<Drawable>get(), factory.build(true /*isFromMemoryCache*/, true /*isFirstResource*/));
}
@Test
public void testReturnsReturnsAnimationIfNotFromMemoryCacheAndIsFirstResource() {
assertNotEquals(NoAnimation.<Drawable>get(),
factory.build(false /*isFromMemoryCache*/, true /*isFirstResource*/));
}
@Test
public void testReturnsAnimationIfNotFromMemocyCacheAndNotIsFirstResource() {
assertNotEquals(NoAnimation.<Drawable>get(),
factory.build(false /*isFromMemoryCache*/, false /*isFirstResource*/));
}
}
\ No newline at end of file
package com.bumptech.glide.request.animation;
import android.view.View;
import android.view.animation.Animation;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@RunWith(JUnit4.class)
public class ViewAnimationFactoryTest {
private ViewAnimation.AnimationFactory animationFactory;
private ViewAnimationFactory<Object> factory;
@Before
public void setUp() {
animationFactory = mock(ViewAnimation.AnimationFactory.class);
factory = new ViewAnimationFactory<Object>(animationFactory);
}
@Test
public void testFactoryReturnsNoAnimationIfFromMemoryCache() {
GlideAnimation<Object> animation = factory.build(true /*isFromMemoryCache*/, true /*isFirstResource*/);
assertEquals(NoAnimation.get(), animation);
verify(animationFactory, never()).build();
}
@Test
public void testFactoryReturnsNoAnimationIfNotFirstResource() {
GlideAnimation<Object> animation = factory.build(false /*isFromMemoryCache*/, false /*isFirstResource*/);
assertEquals(NoAnimation.get(), animation);
verify(animationFactory, never()).build();
}
@Test
public void testFactoryReturnsActualAnimationIfNotIsFromMemoryCacheAndIsFirstResource() {
GlideAnimation<Object> glideAnimation = factory.build(false /*isFromMemoryCache*/, true /*isFirstResource*/);
Animation animation = mock(Animation.class);
when(animationFactory.build()).thenReturn(animation);
GlideAnimation.ViewAdapter adapter = mock(GlideAnimation.ViewAdapter.class);
View view = mock(View.class);
when(adapter.getView()).thenReturn(view);
glideAnimation.animate(new Object(), adapter);
verify(view).startAnimation(eq(animation));
}
}
\ No newline at end of file
package com.bumptech.glide.request.animation;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.Mockito.mock;
@RunWith(JUnit4.class)
public class ViewPropertyAnimationFactoryTest {
private ViewPropertyAnimationFactory<Object> factory;
@Before
public void setUp() {
ViewPropertyAnimation.Animator animator = mock(ViewPropertyAnimation.Animator.class);
factory = new ViewPropertyAnimationFactory<Object>(animator);
}
@Test
public void testReturnsNoAnimationIfFromMemoryCache() {
assertEquals(NoAnimation.get(), factory.build(true /*isFromMemoryCache*/, true /*isFirstResource*/));
}
@Test
public void testReturnsNoAnimationIfNotFirstResource() {
assertEquals(NoAnimation.get(), factory.build(false /*isFromMemoryCache*/, false /*isFirstResource*/));
}
@Test
public void testReturnsAnimationIfNotFromMemoryCacheAndFirstResource() {
assertNotEquals(NoAnimation.get(), factory.build(false /*isFromMemoryCache*/, true /*isFirstResource*/));
}
}
\ No newline at end of file
......@@ -21,7 +21,7 @@ import com.bumptech.glide.manager.Lifecycle;
import com.bumptech.glide.manager.RequestTracker;
import com.bumptech.glide.provider.LoadProvider;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.animation.DrawableCrossFadeViewAnimation;
import com.bumptech.glide.request.animation.DrawableCrossFadeFactory;
import com.bumptech.glide.request.animation.ViewPropertyAnimation;
import com.bumptech.glide.request.target.Target;
......@@ -242,7 +242,7 @@ public class DrawableRequestBuilder<ModelType>
* {@inheritDoc}
*/
public final DrawableRequestBuilder<ModelType> crossFade() {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GlideDrawable>());
super.animate(new DrawableCrossFadeFactory<GlideDrawable>());
return this;
}
......@@ -250,7 +250,7 @@ public class DrawableRequestBuilder<ModelType>
* {@inheritDoc}
*/
public DrawableRequestBuilder<ModelType> crossFade(int duration) {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GlideDrawable>(duration));
super.animate(new DrawableCrossFadeFactory<GlideDrawable>(duration));
return this;
}
......@@ -259,7 +259,7 @@ public class DrawableRequestBuilder<ModelType>
*/
@Deprecated
public DrawableRequestBuilder<ModelType> crossFade(Animation animation, int duration) {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GlideDrawable>(animation, duration));
super.animate(new DrawableCrossFadeFactory<GlideDrawable>(animation, duration));
return this;
}
......@@ -267,7 +267,7 @@ public class DrawableRequestBuilder<ModelType>
* {@inheritDoc}
*/
public DrawableRequestBuilder<ModelType> crossFade(int animationId, int duration) {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GlideDrawable>(context, animationId,
super.animate(new DrawableCrossFadeFactory<GlideDrawable>(context, animationId,
duration));
return this;
}
......
......@@ -4,7 +4,6 @@ import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.animation.Animation;
import android.widget.ImageView;
import com.bumptech.glide.signature.EmptySignature;
import com.bumptech.glide.load.Encoder;
import com.bumptech.glide.load.Key;
import com.bumptech.glide.load.MultiTransformation;
......@@ -27,10 +26,12 @@ import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.ThumbnailRequestCoordinator;
import com.bumptech.glide.request.animation.GlideAnimationFactory;
import com.bumptech.glide.request.animation.NoAnimation;
import com.bumptech.glide.request.animation.ViewAnimation;
import com.bumptech.glide.request.animation.ViewAnimationFactory;
import com.bumptech.glide.request.animation.ViewPropertyAnimation;
import com.bumptech.glide.request.animation.ViewPropertyAnimationFactory;
import com.bumptech.glide.request.target.PreloadTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.signature.EmptySignature;
import com.bumptech.glide.util.Util;
import java.io.File;
......@@ -367,7 +368,7 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT
* @return This request builder.
*/
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> animate(int animationId) {
return animate(new ViewAnimation.ViewAnimationFactory<TranscodeType>(context, animationId));
return animate(new ViewAnimationFactory<TranscodeType>(context, animationId));
}
/**
......@@ -387,7 +388,7 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT
*/
@Deprecated
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> animate(Animation animation) {
return animate(new ViewAnimation.ViewAnimationFactory<TranscodeType>(animation));
return animate(new ViewAnimationFactory<TranscodeType>(animation));
}
/**
......@@ -400,7 +401,7 @@ public class GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeT
*/
public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> animate(
ViewPropertyAnimation.Animator animator) {
return animate(new ViewPropertyAnimation.ViewPropertyAnimationFactory<TranscodeType>(animator));
return animate(new ViewPropertyAnimationFactory<TranscodeType>(animator));
}
GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> animate(
......
......@@ -15,7 +15,7 @@ import com.bumptech.glide.load.resource.gif.GifDrawableTransformation;
import com.bumptech.glide.load.resource.transcode.ResourceTranscoder;
import com.bumptech.glide.provider.LoadProvider;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.animation.DrawableCrossFadeViewAnimation;
import com.bumptech.glide.request.animation.DrawableCrossFadeFactory;
import com.bumptech.glide.request.animation.ViewPropertyAnimation;
import java.io.File;
......@@ -229,7 +229,7 @@ public class GifRequestBuilder<ModelType>
*/
@Override
public GifRequestBuilder<ModelType> crossFade() {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GifDrawable>());
super.animate(new DrawableCrossFadeFactory<GifDrawable>());
return this;
}
......@@ -238,7 +238,7 @@ public class GifRequestBuilder<ModelType>
*/
@Override
public GifRequestBuilder<ModelType> crossFade(int duration) {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GifDrawable>(duration));
super.animate(new DrawableCrossFadeFactory<GifDrawable>(duration));
return this;
}
......@@ -248,7 +248,7 @@ public class GifRequestBuilder<ModelType>
@Deprecated
@Override
public GifRequestBuilder<ModelType> crossFade(Animation animation, int duration) {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GifDrawable>(animation, duration));
super.animate(new DrawableCrossFadeFactory<GifDrawable>(animation, duration));
return this;
}
......@@ -257,7 +257,7 @@ public class GifRequestBuilder<ModelType>
*/
@Override
public GifRequestBuilder<ModelType> crossFade(int animationId, int duration) {
super.animate(new DrawableCrossFadeViewAnimation.DrawableCrossFadeFactory<GifDrawable>(context, animationId,
super.animate(new DrawableCrossFadeFactory<GifDrawable>(context, animationId,
duration));
return this;
}
......
package com.bumptech.glide.request.animation;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
/**
* A factory class that produces a new {@link com.bumptech.glide.request.animation.GlideAnimation} that varies depending
* on whether or not the drawable was loaded from the memory cache and whether or not the drawable is the first
* image to be set on the target.
*
* <p>
* Resources are usually loaded from the memory cache just before the user can see the view,
* for example when the user changes screens or scrolls back and forth in a list. In those cases the user
* typically does not expect to see an animation. As a result, when the resource is loaded from the memory
* cache this factory produces an {@link com.bumptech.glide.request.animation.NoAnimation}.
* </p>
*
* @param <T> The type of the {@link android.graphics.drawable.Drawable} that will be animated.
*/
public class DrawableCrossFadeFactory<T extends Drawable> implements GlideAnimationFactory<T> {
private static final int DEFAULT_DURATION_MS = 300;
private final ViewAnimationFactory<T> animationFactory;
private final int duration;
private DrawableCrossFadeViewAnimation<T> animation;
public DrawableCrossFadeFactory() {
this(DEFAULT_DURATION_MS);
}
public DrawableCrossFadeFactory(int duration) {
this(new ViewAnimationFactory<T>(new DefaultAnimationFactory()), duration);
}
public DrawableCrossFadeFactory(Context context, int defaultAnimationId, int duration) {
this(new ViewAnimationFactory<T>(context, defaultAnimationId), duration);
}
public DrawableCrossFadeFactory(Animation defaultAnimation, int duration) {
this(new ViewAnimationFactory<T>(defaultAnimation), duration);
}
DrawableCrossFadeFactory(ViewAnimationFactory<T> animationFactory, int duration) {
this.animationFactory = animationFactory;
this.duration = duration;
}
@Override
public GlideAnimation<T> build(boolean isFromMemoryCache, boolean isFirstResource) {
if (isFromMemoryCache) {
return NoAnimation.get();
}
if (animation == null) {
GlideAnimation<T> defaultAnimation = animationFactory.build(false, isFirstResource);
animation = new DrawableCrossFadeViewAnimation<T>(defaultAnimation, duration);
}
return animation;
}
private static class DefaultAnimationFactory implements ViewAnimation.AnimationFactory {
@Override
public Animation build() {
AlphaAnimation animation = new AlphaAnimation(0f, 1f);
animation.setDuration(DEFAULT_DURATION_MS / 2);
return animation;
}
}
}
package com.bumptech.glide.request.animation;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
/**
* A cross fade {@link GlideAnimation} for {@link android.graphics.drawable.Drawable}s
......@@ -15,64 +12,9 @@ import android.view.animation.Animation;
* @param <T> The type of the {@link android.graphics.drawable.Drawable} that will be animated.
*/
public class DrawableCrossFadeViewAnimation<T extends Drawable> implements GlideAnimation<T> {
// 150 ms.
public static final int DEFAULT_DURATION = 300;
private final GlideAnimation<T> defaultAnimation;
private final int duration;
/**
* A factory class that produces a new {@link GlideAnimation} that varies depending
* on whether or not the drawable was loaded from the memory cache and whether or not the drawable is the first
* image to be set on the target.
*
* <p>
* Resources are usually loaded from the memory cache just before the user can see the view,
* for example when the user changes screens or scrolls back and forth in a list. In those cases the user
* typically does not expect to see an animation. As a result, when the resource is loaded from the memory
* cache this factory producdes an {@link NoAnimation}.
* </p>
*/
public static class DrawableCrossFadeFactory<T extends Drawable> implements GlideAnimationFactory<T> {
private final ViewAnimation.ViewAnimationFactory<T> animationFactory;
private final int duration;
private DrawableCrossFadeViewAnimation<T> animation;
public DrawableCrossFadeFactory() {
this(DEFAULT_DURATION);
}
public DrawableCrossFadeFactory(int duration) {
this(new ViewAnimation.ViewAnimationFactory<T>(new DefaultAnimationFactory()), duration);
}
public DrawableCrossFadeFactory(Context context, int defaultAnimationId, int duration) {
this(new ViewAnimation.ViewAnimationFactory<T>(context, defaultAnimationId), duration);
}
public DrawableCrossFadeFactory(Animation defaultAnimation, int duration) {
this(new ViewAnimation.ViewAnimationFactory<T>(defaultAnimation), duration);
}
DrawableCrossFadeFactory(ViewAnimation.ViewAnimationFactory<T> animationFactory, int duration) {
this.animationFactory = animationFactory;
this.duration = duration;
}
@Override
public GlideAnimation<T> build(boolean isFromMemoryCache, boolean isFirstResource) {
if (isFromMemoryCache) {
return NoAnimation.get();
}
if (animation == null) {
GlideAnimation<T> defaultAnimation = animationFactory.build(false, isFirstResource);
animation = new DrawableCrossFadeViewAnimation<T>(defaultAnimation, duration);
}
return animation;
}
}
/**
* Constructor that takes a default animation and a duration in milliseconds that the cross fade animation should
* last.
......@@ -111,14 +53,4 @@ public class DrawableCrossFadeViewAnimation<T extends Drawable> implements Glide
return false;
}
}
private static class DefaultAnimationFactory implements ViewAnimation.AnimationFactory {
@Override
public Animation build() {
AlphaAnimation animation = new AlphaAnimation(0f, 1f);
animation.setDuration(DEFAULT_DURATION / 2);
return animation;
}
}
}
package com.bumptech.glide.request.animation;
import android.content.Context;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
/**
* A {@link com.bumptech.glide.request.animation.GlideAnimation GlideAnimation} that can apply a
......@@ -45,76 +43,6 @@ public class ViewAnimation<R> implements GlideAnimation<R> {
return false;
}
/**
* A {@link com.bumptech.glide.request.animation.GlideAnimationFactory} that produces ViewAnimations.
*/
public static class ViewAnimationFactory<R> implements GlideAnimationFactory<R> {
private final AnimationFactory animationFactory;
private GlideAnimation<R> glideAnimation;
public ViewAnimationFactory(Animation animation) {
this(new ConcreteAnimationFactory(animation));
}
public ViewAnimationFactory(Context context, int animationId) {
this(new ResourceAnimationFactory(context, animationId));
}
ViewAnimationFactory(AnimationFactory animationFactory) {
this.animationFactory = animationFactory;
}
/**
* Returns a new {@link com.bumptech.glide.request.animation.GlideAnimation} for the given arguments. If
* isFromMemoryCache is {@code true} or isFirstImage is {@code false}, returns a
* {@link com.bumptech.glide.request.animation.NoAnimation} and otherwise returns a new
* {@link com.bumptech.glide.request.animation.ViewAnimation}.
*
* @param isFromMemoryCache {@inheritDoc}
* @param isFirstResource {@inheritDoc}
*/
@Override
public GlideAnimation<R> build(boolean isFromMemoryCache, boolean isFirstResource) {
if (isFromMemoryCache || !isFirstResource) {
return NoAnimation.get();
}
if (glideAnimation == null) {
glideAnimation = new ViewAnimation<R>(animationFactory);
}
return glideAnimation;
}
}
private static class ConcreteAnimationFactory implements AnimationFactory {
private final Animation animation;
public ConcreteAnimationFactory(Animation animation) {
this.animation = animation;
}
@Override
public Animation build() {
return animation;
}
}
private static class ResourceAnimationFactory implements AnimationFactory {
private final Context context;
private final int animationId;
public ResourceAnimationFactory(Context context, int animationId) {
this.context = context.getApplicationContext();
this.animationId = animationId;
}
@Override
public Animation build() {
return AnimationUtils.loadAnimation(context, animationId);
}
}
interface AnimationFactory {
Animation build();
}
......
package com.bumptech.glide.request.animation;
import android.content.Context;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
/**
* A {@link com.bumptech.glide.request.animation.GlideAnimationFactory} that produces
* {@link com.bumptech.glide.request.animation.ViewAnimation}s.
*
* @param <R> The type of the resource displayed in the view that is animated
*/
public class ViewAnimationFactory<R> implements GlideAnimationFactory<R> {
private final ViewAnimation.AnimationFactory animationFactory;
private GlideAnimation<R> glideAnimation;
public ViewAnimationFactory(Animation animation) {
this(new ConcreteAnimationFactory(animation));
}
public ViewAnimationFactory(Context context, int animationId) {
this(new ResourceAnimationFactory(context, animationId));
}
ViewAnimationFactory(ViewAnimation.AnimationFactory animationFactory) {
this.animationFactory = animationFactory;
}
/**
* Returns a new {@link com.bumptech.glide.request.animation.GlideAnimation} for the given arguments. If
* isFromMemoryCache is {@code true} or isFirstImage is {@code false}, returns a
* {@link com.bumptech.glide.request.animation.NoAnimation} and otherwise returns a new
* {@link com.bumptech.glide.request.animation.ViewAnimation}.
*
* @param isFromMemoryCache {@inheritDoc}
* @param isFirstResource {@inheritDoc}
*/
@Override
public GlideAnimation<R> build(boolean isFromMemoryCache, boolean isFirstResource) {
if (isFromMemoryCache || !isFirstResource) {
return NoAnimation.get();
}
if (glideAnimation == null) {
glideAnimation = new ViewAnimation<R>(animationFactory);
}
return glideAnimation;
}
private static class ConcreteAnimationFactory implements ViewAnimation.AnimationFactory {
private final Animation animation;
public ConcreteAnimationFactory(Animation animation) {
this.animation = animation;
}
@Override
public Animation build() {
return animation;
}
}
private static class ResourceAnimationFactory implements ViewAnimation.AnimationFactory {
private final Context context;
private final int animationId;
public ResourceAnimationFactory(Context context, int animationId) {
this.context = context.getApplicationContext();
this.animationId = animationId;
}
@Override
public Animation build() {
return AnimationUtils.loadAnimation(context, animationId);
}
}
}
......@@ -54,34 +54,4 @@ public class ViewPropertyAnimation<R> implements GlideAnimation<R> {
void animate(View view);
}
/**
* A {@link com.bumptech.glide.request.animation.GlideAnimationFactory} that produces ViewPropertyAnimations.
*/
public static class ViewPropertyAnimationFactory<R> implements GlideAnimationFactory<R> {
private final Animator animator;
private ViewPropertyAnimation<R> animation;
public ViewPropertyAnimationFactory(Animator animator) {
this.animator = animator;
}
/**
* Returns a new {@link com.bumptech.glide.request.animation.GlideAnimation} for the given arguments. If
* isMemoryCache is {@code true} or isFirstImage is {@code false}, returns a
* {@link com.bumptech.glide.request.animation.NoAnimation} and otherwise returns a new
* {@link com.bumptech.glide.request.animation.ViewPropertyAnimation} for the
* {@link com.bumptech.glide.request.animation.ViewPropertyAnimation.Animator} provided in the constructor.
*/
@Override
public GlideAnimation<R> build(boolean isFromMemoryCache, boolean isFirstResource) {
if (isFromMemoryCache || !isFirstResource) {
return NoAnimation.get();
}
if (animation == null) {
animation = new ViewPropertyAnimation<R>(animator);
}
return animation;
}
}
}
package com.bumptech.glide.request.animation;
/**
* A {@link GlideAnimationFactory} that produces ViewPropertyAnimations.
*
* @param <R> The type of the resource displayed in the view that is animated
*/
public class ViewPropertyAnimationFactory<R> implements GlideAnimationFactory<R> {
private final ViewPropertyAnimation.Animator animator;
private ViewPropertyAnimation<R> animation;
public ViewPropertyAnimationFactory(ViewPropertyAnimation.Animator animator) {
this.animator = animator;
}
/**
* Returns a new {@link GlideAnimation} for the given arguments. If
* isMemoryCache is {@code true} or isFirstImage is {@code false}, returns a
* {@link NoAnimation} and otherwise returns a new
* {@link ViewPropertyAnimation} for the
* {@link com.bumptech.glide.request.animation.ViewPropertyAnimation.Animator} provided in the constructor.
*/
@Override
public GlideAnimation<R> build(boolean isFromMemoryCache, boolean isFirstResource) {
if (isFromMemoryCache || !isFirstResource) {
return NoAnimation.get();
}
if (animation == null) {
animation = new ViewPropertyAnimation<R>(animator);
}
return animation;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册