Generated API
About
Glide v4 uses an annotation processor to generate an API that allows applications to access all options in RequestBuilder
, RequestOptions
and any included integration libraries in a single fluent API.
The generated API serves two purposes:
- Integration libraries can extend Glide’s API with custom options.
- Applications can extend Glide’s API by adding methods that bundle commonly used options.
Although both of these tasks can be accomplished by hand by writing custom subclasses of RequestOptions
, doing so is challenging and produces a less fluent API.
Getting Started
Availability
The generated API is only available for applications for now. Limiting the generated API to applications allows us to have a single implementation of the API, instead of N implementations, one per library and the application. As a result, it’s much simpler to manage imports and ensure that all call paths within a particular application have the correct options applied. This restriction may be lifted (experimentally or otherwise) in a future version.
For now the API is only generated when a properly annotated AppGlideModule
is found. There can only be one AppGlideModule
per application. As a result it’s not possible to generate the API for a library without precluding any application that uses the library from using the generated API.
Java
To use the generated API in your application, you need to perform two steps:
-
Add a dependency on Glide’s annotation processor:
repositories { mavenCentral() } dependencies { annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0' }
See the download and setup page for more detail.
-
Include a
AppGlideModule
implementation in your application:package com.example.myapp; import com.bumptech.glide.annotation.GlideModule; import com.bumptech.glide.module.AppGlideModule; @GlideModule public final class MyAppGlideModule extends AppGlideModule {}
You’re not required to implement any of the methods in AppGlideModule
for the API to be generated. You can leave the class blank as long as it extends AppGlideModule
and is annotated with @GlideModule
.
AppGlideModule
implementations must always be annotated with @GlideModule
. If the annotation is not present, the module will not be discovered and you will see a warning in your logs with the Glide
log tag that indicates that the module couldn’t be found.
Note: Libraries should not include AppGlideModule
implementations. See the configuration page for details.
Kotlin
If you’re using Kotlin you can:
- Implement all of Glide’s annotated classes (
AppGlideModule
,LibraryGlideModule
, andGlideExtension
) in Java as shown above. -
Implement the annotated classes in Kotlin, but add a
kapt
dependency instead of anannotationProcessor
dependency on Glide’s annotation processor:dependencies { kapt 'com.github.bumptech.glide:compiler:4.8.0' }
Note that you must also include the
kotlin-kapt
plugin in yourbuild.gradle
file:apply plugin: 'kotlin-kapt'
In addition, if you have any other annotation processors, all of them must be converted from
annotationProcessor
tokapt
:dependencies { kapt "android.arch.lifecycle:compiler:1.0.0" kapt 'com.github.bumptech.glide:compiler:4.8.0' }
For more details on
kapt
, see the official documentation.
Android Studio
For the most part Android Studio just works with annotation processors and the generated API. However, you may need to rebuild the project the first time you add your AppGlideModule
or after some types of changes. If the API won’t import or seems out of date, you can re-build by:
- Open the Build menu
- Click Rebuild Project.
Using the generated API
The API is generated in the same package as the AppGlideModule
implementation provided by the application and is named GlideApp
by default. Applications can use the API by starting all loads with GlideApp.with()
instead of Glide.with()
:
GlideApp.with(fragment)
.load(myUrl)
.placeholder(R.drawable.placeholder)
.fitCenter()
.into(imageView);
Unlike Glide.with()
options like fitCenter()
and placeholder()
are available directly on the builder and don’t need to be passed in as a separate RequestOptions
object.
GlideExtension
Glide’s generated API can be extended by both Applications and Libraries. Extensions use annotated static methods to add new options, modifying existing options, or add additional types.
The GlideExtension
annotation identifies a class that extends Glide’s API. The annotation must be present on any classes that extend Glide’s API. If the annotation is not present, annotations on methods will be ignored.
Classes annotated with GlideExtension
are expected to be utility classes. They should have a private and empty constructor. Classes annotated with GlideExtension should also be final and contain only static methods. Annotated classes may contain static variables and may reference other classes or objects.
An application may implement as many GlideExtension
annotated classes as they’d like. Libraries can also implement an arbitrary number of GlideExtension
annotated classes. When a AppGlideModule
is found, all available GlideExtensions
will be merged to create a single API with all available extensions. Conflicts will result in compilation errors in Glide’s annotation processor.
GlideExtension annotated classes can define two types of extension methods:
GlideOption
- Adds a custom option toRequestOptions
.GlideType
- Adds support for a new resource type (GIFs, SVG etc).
GlideOption
GlideOption
annotated static methods extend RequestOptions
. GlideOption
is useful to:
- Define a group of options that is used frequently throughout an application.
- Add new options, typically in conjunction with Glide’s
Option
class.
To define a group of options, you might write:
@GlideExtension
public class MyAppExtension {
// Size of mini thumb in pixels.
private static final int MINI_THUMB_SIZE = 100;
private MyAppExtension() { } // utility class
@GlideOption
public static void miniThumb(RequestOptions options) {
options
.fitCenter()
.override(MINI_THUMB_SIZE);
}
This will generate a method in a RequestOptions
subclass that looks like this:
public class GlideOptions extends RequestOptions {
public GlideOptions miniThumb() {
MyAppExtension.miniThumb(this);
}
...
}
You can include as many additional arguments in your methods as you want, as long as the first argument is always RequestOptions
:
@GlideOption
public static void miniThumb(RequestOptions options, int size) {
options
.fitCenter()
.override(size);
}
The additional arguments will be added as arguments to the generated method:
public GlideOptions miniThumb(int size) {
MyAppExtension.miniThumb(this);
}
You can then call your custom method by using the generated GlideApp
class:
GlideApp.with(fragment)
.load(url)
.miniThumb(thumbnailSize)
.into(imageView);
Methods with the GlideOption
annotation are expected to be static and to return void. Note that the generated methods will not be available on the standard Glide
and RequestOptions
classes.
GlideType
GlideType
annotated static methods extend RequestManager
. GlideType
annotated methods allow you to add support for new types, including specifying default options.
For example, to add support for GIFs, you might add a GlideType
method:
@GlideExtension
public class MyAppExtension {
private static final RequestOptions DECODE_TYPE_GIF = decodeTypeOf(GifDrawable.class).lock();
@GlideType(GifDrawable.class)
public static void asGif(RequestBuilder<GifDrawable> requestBuilder) {
requestBuilder
.transition(new DrawableTransitionOptions())
.apply(DECODE_TYPE_GIF);
}
}
Doing so will generate a RequestManager
with a method that looks like this:
public class GlideRequests extends RequesetManager {
public RequestBuilder<GifDrawable> asGif() {
RequestBuilder<GifDrawable> builder = as(GifDrawable.class);
MyAppExtension.asGif(builder);
return builder;
}
...
}
You can then use the generated GlideApp
class to call your custom type:
GlideApp.with(fragment)
.asGif()
.load(url)
.into(imageView);
Methods annotated with GlideType
must take a RequestBuilder<T>
as their first argument where the type <T>
matches the class provided to the GlideType
annotation. Methods are expected to be static and return void. Methods must be defined in a class annotated with GlideExtension
.