@Before public void setUp() throws Exception { Glide.tearDown(); RobolectricPackageManager pm = RuntimeEnvironment.getRobolectricPackageManager(); ApplicationInfo info = pm.getApplicationInfo(RuntimeEnvironment.application.getPackageName(), 0); info.metaData = new Bundle(); info.metaData.putString(SetupModule.class.getName(), "GlideModule"); // Ensure that target's size ready callback will be called synchronously. target = mock(Target.class); imageView = new ImageView(RuntimeEnvironment.application); imageView.setLayoutParams(new ViewGroup.LayoutParams(100, 100)); imageView.layout(0, 0, 100, 100); doAnswer(new CallSizeReady()).when(target).getSize(isA(SizeReadyCallback.class)); Handler bgHandler = mock(Handler.class); when(bgHandler.post(isA(Runnable.class))).thenAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { Runnable runnable = (Runnable) invocation.getArguments()[0]; runnable.run(); return true; } }); Lifecycle lifecycle = mock(Lifecycle.class); RequestManagerTreeNode treeNode = mock(RequestManagerTreeNode.class); requestManager = new RequestManager(Glide.get(getContext()), lifecycle, treeNode); requestManager.resumeRequests(); }
@Test public void testClone() throws IOException { Target<Drawable> firstTarget = mock(Target.class); doAnswer(new CallSizeReady(100, 100)).when(firstTarget).getSize(isA(SizeReadyCallback.class)); Target<Drawable> secondTarget = mock(Target.class); doAnswer(new CallSizeReady(100, 100)).when(secondTarget).getSize(isA(SizeReadyCallback.class)); RequestBuilder<Drawable> firstRequest = requestManager .load(mockUri("content://first")); firstRequest.into(firstTarget); firstRequest.clone() .apply(placeholderOf(new ColorDrawable(Color.RED))) .into(secondTarget); verify(firstTarget).onResourceReady(isA(Drawable.class), isA(Transition.class)); verify(secondTarget).onResourceReady(notNull(Drawable.class), isA(Transition.class)); }
@Test public void testCanReRunCancelledRequests() { doAnswer(new CallSizeReady(100, 100)).when(harness.target) .getSize(any(SizeReadyCallback.class)); when(harness.engine .load(eq(harness.glideContext), eq(harness.model), eq(harness.signature), eq(100), eq(100), eq(Object.class), eq(List.class), any(Priority.class), any(DiskCacheStrategy.class), eq(harness.transformations), anyBoolean(), any(Options.class), anyBoolean(), anyBoolean(), anyBoolean(), any(ResourceCallback.class))) .thenAnswer(new CallResourceCallback(harness.resource)); SingleRequest<List> request = harness.getRequest(); request.begin(); request.cancel(); request.begin(); verify(harness.target, times(2)).onResourceReady(eq(harness.result), anyTransition()); }
@Test public void testCallsSourceUnlimitedExecutorEngineIfOptionsIsSet() { doAnswer(new CallSizeReady(100, 100)).when(harness.target) .getSize(any(SizeReadyCallback.class)); harness.useUnlimitedSourceGeneratorsPool = true; SingleRequest<List> request = harness.getRequest(); request.begin(); verify(harness.engine) .load(eq(harness.glideContext), eq(harness.model), eq(harness.signature), anyInt(), anyInt(), eq(Object.class), eq(List.class), any(Priority.class), any(DiskCacheStrategy.class), eq(harness.transformations), anyBoolean(), any(Options.class), anyBoolean(), eq(Boolean.TRUE), anyBoolean(), any(ResourceCallback.class)); }
@Test public void testCallsSourceExecutorEngineIfOptionsIsSet() { doAnswer(new CallSizeReady(100, 100)).when(harness.target) .getSize(any(SizeReadyCallback.class)); harness.useUnlimitedSourceGeneratorsPool = false; SingleRequest<List> request = harness.getRequest(); request.begin(); verify(harness.engine) .load(eq(harness.glideContext), eq(harness.model), eq(harness.signature), anyInt(), anyInt(), eq(Object.class), eq(List.class), any(Priority.class), any(DiskCacheStrategy.class), eq(harness.transformations), anyBoolean(), any(Options.class), anyBoolean(), eq(Boolean.FALSE), anyBoolean(), any(ResourceCallback.class)); }
public static void loadResource(@DrawableRes int drawableId, @NonNull ImageView image) { DisplayMetrics metrics = image.getResources().getDisplayMetrics(); final int w = metrics.widthPixels, h = metrics.heightPixels; Glide.with(image.getContext()) .load(drawableId) .animate(ANIMATOR) .diskCacheStrategy(DiskCacheStrategy.NONE) .into(new GlideDrawableImageViewTarget(image) { @Override public void getSize(final SizeReadyCallback cb) { // We don't want to load very big images on devices with small screens. // This will help Glide correctly choose images scale when reading them. super.getSize(new SizeReadyCallback() { @Override public void onSizeReady(int width, int height) { cb.onSizeReady(w / 2, h / 2); } }); } }); }
@Override public void onBindViewHolder(final ViewHolder holder,final int position) { Girl entity = mListData.get(position); Glide.with(mContext) .load(entity.url) .centerCrop() .into(holder.mIvIndexPhoto) .getSize(new SizeReadyCallback() { @Override public void onSizeReady(int width, int height) { holder.mIvIndexPhoto.setColorFilter(mColorFilter); } }); holder.mTvTime.setText(DateUtil.toDate(entity.publishedAt)); if(mIClickItem!=null){ holder.mIvIndexPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mIClickItem.onClickPhoto(position, holder.mIvIndexPhoto,holder.mTvTime); } }); } }
@Override public void onBindViewHolder(final ViewHolder holder,final int position) { Girl entity = mListData.get(position); Glide.with(mContext) .load(entity.url) .centerCrop() .diskCacheStrategy(DiskCacheStrategy.ALL) .dontAnimate() .into(holder.mIvIndexPhoto) .getSize(new SizeReadyCallback() { @Override public void onSizeReady(int width, int height) { //holder.mIvIndexPhoto.setColorFilter(mColorFilter); } }); holder.mTvTime.setText(DateUtil.toDate(entity.publishedAt)); if(mIClickItem!=null){ holder.mIvIndexPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mIClickItem.onClickPhoto(position, holder.mIvIndexPhoto,holder.mTvTime); } }); } }
@Test public void testCallsGetSizeIfOverrideWidthIsLessThanZero() { harness.overrideWidth = -1; harness.overrideHeight = 100; SingleRequest<List> request = harness.getRequest(); request.begin(); verify(harness.target).getSize(any(SizeReadyCallback.class)); }
@Test public void testCallsGetSizeIfOverrideHeightIsLessThanZero() { harness.overrideHeight = -1; harness.overrideWidth = 100; SingleRequest<List> request = harness.getRequest(); request.begin(); verify(harness.target).getSize(any(SizeReadyCallback.class)); }
@Test public void testDoesNotCallGetSizeIfOverrideWidthAndHeightAreSet() { harness.overrideWidth = 100; harness.overrideHeight = 100; SingleRequest<List> request = harness.getRequest(); request.begin(); verify(harness.target, never()).getSize(any(SizeReadyCallback.class)); }
private <R> List<Integer> getTargetsSizes( RequestBuilder<R> requestBuilder, VerificationMode mode) { ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class); ArgumentCaptor<Target<R>> targetArgumentCaptor = cast(ArgumentCaptor.forClass(Target.class)); SizeReadyCallback cb = mock(SizeReadyCallback.class); verify(requestBuilder, mode).into(targetArgumentCaptor.capture()); for (Target<R> target : targetArgumentCaptor.getAllValues()) { target.getSize(cb); } verify(cb, mode).onSizeReady(integerArgumentCaptor.capture(), integerArgumentCaptor.capture()); return integerArgumentCaptor.getAllValues(); }
@Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); context = RuntimeEnvironment.application; // Run all tasks on the main thread so they complete synchronously. GlideExecutor executor = MockGlideExecutor.newMainThreadExecutor(); when(diskCacheFactory.build()).thenReturn(diskCache); Glide.init( context, new GlideBuilder() .setMemoryCache(memoryCache) .setDiskCache(diskCacheFactory) .setSourceExecutor(executor) .setDiskCacheExecutor(executor)); Registry registry = Glide.get(context).getRegistry(); registerMockModelLoader( GlideUrl.class, InputStream.class, new ByteArrayInputStream(new byte[0]), registry); registerMockModelLoader( File.class, InputStream.class, new ByteArrayInputStream(new byte[0]), registry); registerMockModelLoader( File.class, ParcelFileDescriptor.class, mock(ParcelFileDescriptor.class), registry); registerMockModelLoader(File.class, ByteBuffer.class, ByteBuffer.allocate(10), registry); // Ensure that target's size ready callback will be called synchronously. imageView = new ImageView(context); imageView.setLayoutParams(new ViewGroup.LayoutParams(100, 100)); imageView.layout(0, 0, 100, 100); doAnswer(new CallSizeReady()).when(target).getSize(isA(SizeReadyCallback.class)); when(bgHandler.post(isA(Runnable.class))).thenAnswer(new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { Runnable runnable = (Runnable) invocation.getArguments()[0]; runnable.run(); return true; } }); requestManager = new RequestManager(Glide.get(context), lifecycle, treeNode, context); requestManager.resumeRequests(); }
@Test public void testCallsGetSizeIfOverrideWidthIsLessThanZero() { SingleRequest<List> request = builder .setOverrideWidth(-1) .setOverrideHeight(100) .build(); request.begin(); verify(builder.target).getSize(any(SizeReadyCallback.class)); }
@Test public void testCallsGetSizeIfOverrideHeightIsLessThanZero() { SingleRequest<List> request = builder .setOverrideWidth(100) .setOverrideHeight(-1) .build(); request.begin(); verify(builder.target).getSize(any(SizeReadyCallback.class)); }
@Test public void testDoesNotCallGetSizeIfOverrideWidthAndHeightAreSet() { SingleRequest<List> request = builder .setOverrideWidth(100) .setOverrideHeight(100) .build(); request.begin(); verify(builder.target, never()).getSize(any(SizeReadyCallback.class)); }
@Test public void testCanReRunCancelledRequests() { doAnswer(new CallSizeReady(100, 100)).when(builder.target) .getSize(any(SizeReadyCallback.class)); when(builder.engine .load( eq(builder.glideContext), eq(builder.model), eq(builder.signature), eq(100), eq(100), eq(Object.class), eq(List.class), any(Priority.class), any(DiskCacheStrategy.class), eq(builder.transformations), anyBoolean(), anyBoolean(), any(Options.class), anyBoolean(), anyBoolean(), /*useAnimationPool=*/ anyBoolean(), anyBoolean(), any(ResourceCallback.class))) .thenAnswer(new CallResourceCallback(builder.resource)); SingleRequest<List> request = builder.build(); request.begin(); request.cancel(); request.begin(); verify(builder.target, times(2)).onResourceReady(eq(builder.result), anyTransition()); }
@Test public void testCallsSourceUnlimitedExecutorEngineIfOptionsIsSet() { doAnswer(new CallSizeReady(100, 100)).when(builder.target) .getSize(any(SizeReadyCallback.class)); SingleRequest<List> request = builder .setUseUnlimitedSourceGeneratorsPool(true) .build(); request.begin(); verify(builder.engine) .load( eq(builder.glideContext), eq(builder.model), eq(builder.signature), anyInt(), anyInt(), eq(Object.class), eq(List.class), any(Priority.class), any(DiskCacheStrategy.class), eq(builder.transformations), anyBoolean(), anyBoolean(), any(Options.class), anyBoolean(), eq(true), /*useAnimationPool=*/ anyBoolean(), anyBoolean(), any(ResourceCallback.class)); }
@Test public void testCallsSourceExecutorEngineIfOptionsIsSet() { doAnswer(new CallSizeReady(100, 100)).when(builder.target) .getSize(any(SizeReadyCallback.class)); SingleRequest<List> request = builder .setUseUnlimitedSourceGeneratorsPool(false) .build(); request.begin(); verify(builder.engine) .load( eq(builder.glideContext), eq(builder.model), eq(builder.signature), anyInt(), anyInt(), eq(Object.class), eq(List.class), any(Priority.class), any(DiskCacheStrategy.class), eq(builder.transformations), anyBoolean(), anyBoolean(), any(Options.class), anyBoolean(), eq(false), /*useAnimationPool=*/ anyBoolean(), anyBoolean(), any(ResourceCallback.class)); }
private <Resource> List<Integer> getTargetsSizes( RequestBuilder<Resource> requestBuilder, VerificationMode mode) { ArgumentCaptor<Integer> integerArgumentCaptor = ArgumentCaptor.forClass(Integer.class); ArgumentCaptor<Target<Resource>> targetArgumentCaptor = cast(ArgumentCaptor.forClass(Target.class)); SizeReadyCallback cb = mock(SizeReadyCallback.class); verify(requestBuilder, mode).into(targetArgumentCaptor.capture()); for (Target<Resource> target : targetArgumentCaptor.getAllValues()) { target.getSize(cb); } verify(cb, mode).onSizeReady(integerArgumentCaptor.capture(), integerArgumentCaptor.capture()); return integerArgumentCaptor.getAllValues(); }
@Before public void setUp() { MockitoAnnotations.initMocks(this); context = RuntimeEnvironment.application; connectivityMonitor = mock(ConnectivityMonitor.class); ConnectivityMonitorFactory factory = mock(ConnectivityMonitorFactory.class); when(factory.build(isA(Context.class), isA(ConnectivityMonitor.ConnectivityListener.class))) .thenAnswer(new Answer<ConnectivityMonitor>() { @Override public ConnectivityMonitor answer(InvocationOnMock invocation) throws Throwable { connectivityListener = (ConnectivityListener) invocation.getArguments()[1]; return connectivityMonitor; } }); target = new BaseTarget<Drawable>() { @Override public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) { // Empty. } @Override public void getSize(SizeReadyCallback cb) { // Empty. } @Override public void removeCallback(SizeReadyCallback cb) { // Empty. } }; requestTracker = mock(RequestTracker.class); manager = new RequestManager( Glide.get(RuntimeEnvironment.application), lifecycle, treeNode, requestTracker, factory, context); }
@Override public void getSize(SizeReadyCallback cb) { // FIXME 这里为了图方面,直接加载原图了,生产环境上应该是高和宽都取mView.getDrawableSize()。 // 但是这里直接取的话也不一定能取到正确的值,所以建义在 // android.view.ViewTreeObserver.OnPreDrawListener中做处理。 // 另外,DrawableSize会因图片数量改变而改变,所以建义异步加载图像之前 // 应当先设置占位图。如果图片的数量是动态可变的的话,也建义做针对性处理。 cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL); }
/** * @param view 要展示的控件 * @param url 要展示的地址 * @param defaultImage 默认显示的图片 */ private static void displayUrl(final ImageView view, String url, @DrawableRes int defaultImage) { // 不能崩 if (view == null) { return; } Context context = view.getContext(); // View还活着吗? if (context instanceof Activity) { if (((Activity) context).isFinishing()) { return; } } try { Glide.with(context) .load(url) .diskCacheStrategy(DiskCacheStrategy.RESULT) .placeholder(defaultImage)//在图片加载完成以前显示占位符 .crossFade() .error(defaultImage) .dontAnimate() .centerCrop() .into(view) .getSize(new SizeReadyCallback() { @Override public void onSizeReady(int width, int height) { if (!view.isShown()) { view.setVisibility(View.VISIBLE); } } }); } catch (Exception e) { e.printStackTrace(); } }
/** * @param view 要展示的控件 * @param url 要展示的地址 */ private static <T> void displayUrl(final ImageView view, T url) { if (view == null) { return; } Context context = view.getContext(); // View还活着吗? if (context instanceof Activity) { if (((Activity) context).isFinishing()) { return; } } Glide.with(context) .load(url) .diskCacheStrategy(DiskCacheStrategy.RESULT) // .placeholder(defaultImage)//在图片加载完成以前显示占位符 .crossFade()//淡入淡出动画,默认是调用的,可以传毫秒值减慢/加快,动画事件 .dontAnimate()//不展示淡入淡出效果,直接显示图片 .centerCrop()//用上这句就可以填充控件 .into(view) .getSize(new SizeReadyCallback() { @Override public void onSizeReady(int width, int height) { if (!view.isShown()) { view.setVisibility(View.VISIBLE); } } }); }
private void initData() { final Glide glide = Glide.get(this); OkHttpProgressGlideModule a = new OkHttpProgressGlideModule(); a.registerComponents(this, glide); String url = "http://img.tuku.cn/file_big/201502/3d101a2e6cbd43bc8f395750052c8785.jpg"; // String url ="http://img0.ph.126.net/fVdyWijVAOYXq4HbaK1kjQ==/6631927583792333415.jpg"; Glide.with(this).load(url).downloadOnly(new ProgressTarget<String, File>(url, null) { @Override public void onLoadStarted(Drawable placeholder) { super.onLoadStarted(placeholder); ringProgressBar.setVisibility(View.VISIBLE); ringProgressBar.setProgress(0); } @Override public void onProgress(long bytesRead, long expectedLength) { int p = 0; if (expectedLength >= 0) { p = (int) (100 * bytesRead / expectedLength); } ringProgressBar.setProgress(p); } @Override public void onResourceReady(File resource, GlideAnimation<? super File> animation) { super.onResourceReady(resource, animation); ringProgressBar.setVisibility(View.GONE); largeImageView.setImage(new FileBitmapDecoderFactory(resource)); } @Override public void getSize(SizeReadyCallback cb) { cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL); } }); }
@Override public void getSize(SizeReadyCallback cb) { int maxWidth = getRealWidth(), maxHeight = Integer.MAX_VALUE; if (config.imageFixCallback != null) { holder.setImageState(ImageHolder.ImageState.SIZE_READY); ImageHolder.SizeHolder sizeHolder = new ImageHolder.SizeHolder(0, 0); config.imageFixCallback.onSizeReady(holder, 0, 0, sizeHolder); if (sizeHolder.isInvalidateSize()) { maxWidth = sizeHolder.getWidth(); maxHeight = sizeHolder.getHeight(); } } cb.onSizeReady(maxWidth, maxHeight); }
/** * A callback that should never be invoked directly. */ @Override public void getSize(SizeReadyCallback cb) { cb.onSizeReady(width, height); }
@Override public void removeCallback(SizeReadyCallback cb) { // Do nothing because we do not retain references to SizeReadyCallbacks. }
public SizeViewTarget(View view, SizeReadyCallback callback) { super(view); getSize(callback); }
@Override public void getSize(SizeReadyCallback cb) { cb.onSizeReady(photoWidth, photoHeight); }
@Override public void removeCallback(SizeReadyCallback cb) { // Do nothing because we don't retain references to SizeReadyCallbacks. }
@Override public Void answer(InvocationOnMock invocation) throws Throwable { SizeReadyCallback cb = (SizeReadyCallback) invocation.getArguments()[0]; cb.onSizeReady(width, height); return null; }
@Override public Object answer(InvocationOnMock invocationOnMock) throws Throwable { SizeReadyCallback cb = (SizeReadyCallback) invocationOnMock.getArguments()[0]; cb.onSizeReady(width, height); return null; }
@Override public void getSize(SizeReadyCallback cb) { }
@Override public void removeCallback(SizeReadyCallback cb) { // Do nothing. }
@Test public void testCallsSizeReadyCallbackOnGetSize() { SizeReadyCallback cb = mock(SizeReadyCallback.class); future.getSize(cb); verify(cb).onSizeReady(eq(width), eq(height)); }