/** * Prepends the given {@link ResourceDecoder} into the list of all available * {@link ResourceDecoder}s so that it is attempted before all later and default * {@link ResourceDecoder}s for the given types. * * <p>This method allows you to replace the default {@link ResourceDecoder} because it ensures * the registered {@link ResourceDecoder} will run first. You can use the * {@link ResourceDecoder#handles(Object, Options)} to fall back to the default * {@link ResourceDecoder}s if you only want to change the default functionality for certain * types of data. * * @see #prepend(String, Class, Class, ResourceDecoder) * @see #append(Class, Class, ResourceDecoder) * * @param dataClass The data that will be decoded from * ({@link java.io.InputStream}, {@link java.io.FileDescriptor} etc). * @param resourceClass The resource that will be decoded to ({@link android.graphics.Bitmap}, * {@link com.bumptech.glide.load.resource.gif.GifDrawable} etc). * @param decoder The {@link ResourceDecoder} to register. */ @NonNull public <Data, TResource> Registry prepend( @NonNull Class<Data> dataClass, @NonNull Class<TResource> resourceClass, @NonNull ResourceDecoder<Data, TResource> decoder) { prepend(BUCKET_PREPEND_ALL, dataClass, resourceClass, decoder); return this; }
@Override public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) { glide.getRegistry().prepend(CustomImageSizeModel.class, InputStream.class, new CustomImageSizeUrlLoaderFactory()); } }
@SuppressWarnings("unchecked") private <T> void registerMockStreamModelLoader(final Class<T> modelClass) { ModelLoader<T, InputStream> modelLoader = mockStreamModelLoader(modelClass); ModelLoaderFactory<T, InputStream> modelLoaderFactory = mock(ModelLoaderFactory.class); when(modelLoaderFactory.build(isA(MultiModelLoaderFactory.class))).thenReturn(modelLoader); Glide.get(context).getRegistry() .prepend(modelClass, InputStream.class, modelLoaderFactory); }
@SuppressWarnings("unchecked") private <T, Z> void registerFailFactory(Class<T> failModel, Class<Z> failResource) { DataFetcher<Z> failFetcher = mock(DataFetcher.class); doAnswer(new Util.CallDataReady<>(null)) .when(failFetcher) .loadData(isA(Priority.class), isA(DataFetcher.DataCallback.class)); when(failFetcher.getDataClass()).thenReturn(failResource); ModelLoader<T, Z> failLoader = mock(ModelLoader.class); when(failLoader.buildLoadData(isA(failModel), anyInt(), anyInt(), isA(Options.class))) .thenReturn(new ModelLoader.LoadData<>(mock(Key.class), failFetcher)); when(failLoader.handles(isA(failModel))).thenReturn(true); ModelLoaderFactory<T, Z> failFactory = mock(ModelLoaderFactory.class); when(failFactory.build(isA(MultiModelLoaderFactory.class))).thenReturn(failLoader); Glide.get(context).getRegistry().prepend(failModel, failResource, failFactory); }
@Test public void loadJpegResource_withNoOtherLoaders_decodesResource() { Glide.get(context).getRegistry() .prepend( Object.class, InputStream.class, new FakeModelLoader<>(ResourceIds.raw.canonical)); Bitmap bitmap = concurrency.get( Glide.with(context) .asBitmap() .load(new Object()) .submit()); assertThat(bitmap).isNotNull(); }
@Test public void loadOpaqueGifResource_withNoOtherLoaders_decodesResource() { Glide.get(context).getRegistry() .prepend( Object.class, InputStream.class, new FakeModelLoader<>(ResourceIds.raw.opaque_gif)); Bitmap bitmap = concurrency.get( Glide.with(context) .asBitmap() .load(new Object()) .submit()); assertThat(bitmap).isNotNull(); }
@Test public void loadTransparentPngResource_withNoOtherLoaders_decodesResource() { Glide.get(context).getRegistry() .prepend( Object.class, InputStream.class, new FakeModelLoader<>(ResourceIds.raw.canonical_transparent_png)); Bitmap bitmap = concurrency.get( Glide.with(context) .asBitmap() .load(new Object()) .submit()); assertThat(bitmap).isNotNull(); }
@Test public void loadTransparentGifResource_withNoOtherLoaders_decodesResource() { Glide.get(context).getRegistry() .prepend( Object.class, InputStream.class, new FakeModelLoader<>(ResourceIds.raw.transparent_gif)); Bitmap bitmap = concurrency.get( Glide.with(context) .asBitmap() .load(new Object()) .submit()); assertThat(bitmap).isNotNull(); }
@Test public void loadOpaquePngResource_withNoOtherLoaders_decodesResource() { Glide.get(context).getRegistry() .prepend( Object.class, InputStream.class, new FakeModelLoader<>(ResourceIds.raw.canonical_png)); Bitmap bitmap = concurrency.get( Glide.with(context) .asBitmap() .load(new Object()) .submit()); assertThat(bitmap).isNotNull(); }
@Test public void loadWideGamutJpegResource_withNoOtherLoaders_decodesWideGamutBitmap() { assumeTrue( "Wide gamut is only available on O+", Build.VERSION.SDK_INT >= Build.VERSION_CODES.O); Glide.get(context).getRegistry() .prepend( Object.class, InputStream.class, new FakeModelLoader<>(ResourceIds.raw.webkit_logo_p3)); Bitmap bitmap = concurrency.get( Glide.with(context) .asBitmap() .load(new Object()) .submit()); assertThat(bitmap).isNotNull(); assertThat(bitmap.getConfig()).isEqualTo(Bitmap.Config.RGBA_F16); assertThat(bitmap.getColorSpace()) .isEqualTo(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB)); }
@Test public void load_whenLoadSucceeds_butEncoderFails_doesNotCallOnLoadFailed() { WaitForErrorStrategy strategy = new WaitForErrorStrategy(); Glide.init(context, new GlideBuilder() .setAnimationExecutor(GlideExecutor.newAnimationExecutor(/*threadCount=*/ 1, strategy)) .setSourceExecutor(GlideExecutor.newSourceExecutor(strategy)) .setDiskCacheExecutor(GlideExecutor.newDiskCacheExecutor(strategy))); Glide.get(context).getRegistry().prepend(Bitmap.class, new FailEncoder()); concurrency.get( Glide.with(context) .load(ResourceIds.raw.canonical) .listener(requestListener) .submit()); verify(requestListener) .onResourceReady( anyDrawable(), any(), anyDrawableTarget(), any(DataSource.class), anyBoolean()); verify(requestListener, never()) .onLoadFailed(any(GlideException.class), any(), anyDrawableTarget(), anyBoolean()); }
@Test public void loadTransparentGifResource_asHardware_withNoOtherLoaders_decodesResource() { assumeTrue( "Hardware Bitmaps are only supported on O+", Build.VERSION.SDK_INT >= Build.VERSION_CODES.O); Glide.get(context).getRegistry() .prepend( Object.class, InputStream.class, new FakeModelLoader<>(ResourceIds.raw.transparent_gif)); Bitmap bitmap = concurrency.get( GlideApp.with(context) .asBitmap() .set(Downsampler.ALLOW_HARDWARE_CONFIG, true) .format(DecodeFormat.PREFER_ARGB_8888) .load(new Object()) .submit()); assertThat(bitmap).isNotNull(); assertThat(bitmap.getConfig()).isEqualTo(Bitmap.Config.HARDWARE); }
@Test public void load_whenEncoderFails_callsUncaughtThrowableStrategy() { WaitForErrorStrategy strategy = new WaitForErrorStrategy(); Glide.init(context, new GlideBuilder() .setAnimationExecutor(GlideExecutor.newAnimationExecutor(/*threadCount=*/ 1, strategy)) .setSourceExecutor(GlideExecutor.newSourceExecutor(strategy)) .setDiskCacheExecutor(GlideExecutor.newDiskCacheExecutor(strategy))); Glide.get(context).getRegistry().prepend(Bitmap.class, new FailEncoder()); concurrency.get( Glide.with(context) .load(ResourceIds.raw.canonical) .listener(requestListener) .submit()); // Writing to the disk cache and therefore the exception caused by our FailEncoder may happen // after the request completes, so we should wait for the expected error explicitly. ConcurrencyHelper.waitOnLatch(strategy.latch); assertThat(strategy.error).isEqualTo(FailEncoder.TO_THROW); verify(requestListener, never()) .onLoadFailed(any(GlideException.class), any(), anyDrawableTarget(), anyBoolean()); }
@Test public void loadOpaqueGifResource_asHardware_withNoOtherLoaders_decodesResource() { assumeTrue( "Hardware Bitmaps are only supported on O+", Build.VERSION.SDK_INT >= Build.VERSION_CODES.O); Glide.get(context).getRegistry() .prepend( Object.class, InputStream.class, new FakeModelLoader<>(ResourceIds.raw.opaque_gif)); Bitmap bitmap = concurrency.get( GlideApp.with(context) .asBitmap() // Allow HARDWARE Bitmaps. .format(DecodeFormat.PREFER_ARGB_8888) .load(new Object()) .submit()); assertThat(bitmap).isNotNull(); }
/** * Prepends the given {@link ResourceDecoder} into the list of all available * {@link ResourceDecoder}s so that it is attempted before all later and default * {@link ResourceDecoder}s for the given types. * * <p>This method allows you to replace the default {@link ResourceDecoder} because it ensures * the registered {@link ResourceDecoder} will run first. You can use the * {@link ResourceDecoder#handles(Object, Options)} to fall back to the default * {@link ResourceDecoder}s if you only want to change the default functionality for certain * types of data. * * @see #prepend(String, Class, Class, ResourceDecoder) * @see #append(Class, Class, ResourceDecoder) * * @param dataClass The data that will be decoded from * ({@link java.io.InputStream}, {@link java.io.FileDescriptor} etc). * @param resourceClass The resource that will be decoded to ({@link android.graphics.Bitmap}, * {@link com.bumptech.glide.load.resource.gif.GifDrawable} etc). * @param decoder The {@link ResourceDecoder} to register. */ public <Data, TResource> Registry prepend( Class<Data> dataClass, Class<TResource> resourceClass, ResourceDecoder<Data, TResource> decoder) { prepend(BUCKET_PREPEND_ALL, dataClass, resourceClass, decoder); return this; }
@Override public void registerComponents(Context context, Glide glide, Registry registry) { super.registerComponents(context, glide, registry); Log.i(TAG, "registerComponents"); registry.prepend(info.guardianproject.iocipher.File.class, java.io.FileInputStream.class, new com.zoffcc.applications.trifa.FileLoader2.StreamFactory()); }