In this tutorial you can read about Glide. The advanced library for image uploading, caching, rotating and small memory usage.
Android SDK does not have a good way to get images from web and display it to android app. To solve this problem, numbers of third party libraries are available.
You can read some comparison here and here.
Glide features
ImageView
OkHttp
and Volley
libraryGlide offers some additional advantages over other image loading libraries. For example, when loading an image, Glide will cache both a version of the image in its original size as well as one that’s the size of its intended ImageView
. This means Glide loads the image noticeably faster than libraries like Picasso because no resize is necessary. Additionally, Glide works with Android’s ImageView
(Facebook’s Fresco uses DraweeView
and Volley uses NetworkImageView
).
Getting started with Glide is as easy as using Picasso. Their API also look quite similar.
Add the Gradle dependency to your android module build.gradle. Glide also needs android support library v4. Also I'm going to use CircleImageView
for circle effect for image.
dependencies { implementation 'com.github.bumptech.glide:glide:4.7.1' annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1' implementation 'com.android.support:support-v4:23.4.0' implementation 'de.hdodenhof:circleimageview:2.1.0' }
The way to load an image to ImageView
with Glide is quite the same as Picasso.
Glide.with(context).load(url).into(imageView);
Although it looks quite the same but in details Glide is designed far better since with doesn't accept only Context
but also Activity
and Fragment
. The brilliant benefit from passing Activity/Fragment to Glide is: image loading would be integrated with Activity/Fragment's lifecycle for example, pause loading in Paused state and automatically resume on Resumed state.
Most options in Glide can be applied using the RequestOptions
class and the apply()
method.
Use request options to apply (among others):
For example, to apply a CenterCrop
transformation, you’d use the following:
import static com.bumptech.glide.request.RequestOptions.centerCropTransform; Glide.with(context) .load(url) .apply(centerCropTransform(context)) .into(ivPhoto);
Glide is very customizable. Starting with the 4.0 release Glide creates a custom fluent interface depending on your customization. Glide's developers call this result generated API.
In order to create the generated API, which we'll use in all upcoming tutorials, you'll have to create a class extending AppGlideModule
somewhere in your app project:
@GlideModule public final class MyAppGlideModule extends AppGlideModule {}
Don't forget the @GlideModule
! Then, by default, the generated API is accessible via GlideApp
. For example:
ImageView ivPhoto = (ImageView) findViewById(R.id.ivPhoto); GlideApp.with(context).load(url).into(ivPhoto);
Loading image from res/drawable folder
GlideApp.with(context).load(R.drawable.IMAGE_NAME).into(ivPhoto);
Show placeholder image
GlideApp.with(context) .load(url) .placeholder(R.drawable.placeholder) .fitCenter() .into(ivPhoto);
Transform image
GlideApp.with(context) .load(url) .override(WIDTH, HEIGHT) .centerCrop() .into(ivPhoto);
You can load image to Bitmap
via following snippet
GlideApp.with(itemView.getContext()) .asBitmap() .load(data.getImageUrl()) .into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {} preparePhoto(resource); }); }
Let's build simple application that will demonstrates Glide usage
Layout file
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_margin="16dp" android:orientation="vertical"> <de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_gravity="center_horizontal" android:id="@+id/img" android:layout_width="200dp" android:layout_height="200dp" android:src="@drawable/placeholder_img" app:civ_border_width="2dp" app:civ_border_color="#FFFF4081"/> </LinearLayout>
In MainActivity file define variable for ImageView
and set image URL for load
method of Glide. Following is the complete code of java activity file.
public class MainActivity extends AppCompatActivity { CircleImageView img; String url = "http://snovadoma.ru/media/photos/04f631d079c2171827cae83e2ee61c52.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); img = (CircleImageView) findViewById(R.id.img); GlideApp.with(this) .load(url) .placeholder(R.drawable.placeholder_img) .into(img); } }
Result
We can use transformations for crop, blur, color, mask.
Bitmap format
Glide’s default bitmap format is set to RGB_565
so image quality will be poorer compared with Picasso. But the advantage is that it will consume less memory. If you are ok with image quality, don’t change the bitmap format else change it to ARGB_8888
as below.
public class GlideConfiguration implements GlideModule { @Override public void applyOptions(Context context, GlideBuilder builder) { builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); } @Override public void registerComponents(Context context, Glide glide) { // register ModelLoaders here. } }
Then, add meta-tag into AndroidManifest.xml
<meta-data android:name="com.example.proft.GlideConfiguration" android:value="GlideModule"/>
If you run the app, images will look better now.
Image caching
Glide creates cached images per size while Picasso saves the full image and process it. If you are trying to load image (500x500) into ImageView
(200x200). Glide will download full image, then resize it to 200x200, then it will cache and load into ImageView
while Picasso will download full image then it will cache full image then resize it to 200x200 and load it into ImageView.
Next time when you request same image (500x500) to load into ImageView
(100x100), Glide will again download the full image (500x500) then resize it to 100x100 then cache and load into ImageView
. Picasso, unlike Glide, picks up the cached full size image and resize and load it into ImageView
(100x100). Picasso doesn’t download same image again.
However, you can configure Glide to cache full size and resized image as below.
Glide.with(this) .load(url) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(imageView);
Loading Image to Target
If you want to do something with the loaded image, you need to load the request into target instead of view. You can use Glide provided SimpleTarget
class which implements Target
or create custom Target
class to capture downloaded image.
Glide.with(this) .load(productImage) .into(new SimpleTarget<Drawable>() { @Override public void onResourceReady(@NonNull Drawable drawable, @Nullable Transition<? super Drawable> transition) { captureDrawable = drawable; } });
Custom Glide Object
In the example above we used default singleton Glide object for loading images. Glide allows you to build custom Glide object using GlideBuilder
and set the created Glide object as global singleton object using init()
method on Glide class.
GlideBuilder
has various methods to set bitmap pool, array pool, request options, transition options, disk cache, memory cache, and executor service.
private void buildGlide(){ GlideBuilder gb = new GlideBuilder(); //set mem cache size to 8% of available memory LruResourceCache lruMemCache = new LruResourceCache(getMemCacheSize(8)); gb.setMemoryCache(lruMemCache); //set disk cache 300 mb InternalCacheDiskCacheFactory diskCacheFactory = new InternalCacheDiskCacheFactory(this, 300); gb.setDiskCache(diskCacheFactory); //set BitmapPool with 1/10th of memory cache's size LruBitmapPool bitmapPool = new LruBitmapPool(getMemCacheSize(8)/10); gb.setBitmapPool(bitmapPool); //set custom Glide as global singleton Glide.init(this, gb); } private int getMemCacheSize(int percent){ ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); ((ActivityManager) getSystemService(ACTIVITY_SERVICE)).getMemoryInfo(mi); double availableMemory= mi.availMem; return (int)(percent*availableMemory/100); }
Place Holders
You can set an image as place holder that will be displayed while an image loading request is being processed by Glide or if loading of the image fails. To set placeholder and error images, you need to instantiate RequestOptions
object, set placeholder and error images by calling placeholder()
and error()
methods on it. Then add RequestOptions
object to RequestManager
by calling applyDefaultRequestOptions()
method on RequestManager
as shown below.
RequestOptions ro = new RequestOptions(); ro.placeholder(R.drawable.account); ro.error(R.drawable.account_balance); Glide.with(this) .applyDefaultRequestOptions(ro) .load(productImage) .into(imgView);
Image Transitions
You can apply transitions to an image loading request by calling transition()
method on RequestBuilder
, the method takes TransitionOptions
as argument. Transition will be shown while image is being downloaded. That is why image transition will be applied to the image when it is being loaded from disk cache, locally from the device or remotely, but not when it is downloaded from memory cache.
In the example below, transition method is used with DrawableTransitionOptions
. Other Glide provided TransitionOptions
implementations are BitmapTransitionOptions
, DrawableTransitionOptions
, and GenericTransitionOptions
.
Glide.with(this) .load(productImage).transition(DrawableTransitionOptions.withCrossFade()) .into(imgView);
You can use android provided animations with Glide using GenericTransitionOptions.
Glide.with(this) .applyDefaultRequestOptions(ro) .load(productImage).transition(GenericTransitionOptions .with(android.R.anim.slide_in_left)) .into(imgView);
You can define animation in xml use it with Glide.
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="-50%p" android:toXDelta="0" android:duration="@android:integer/config_mediumAnimTime"/> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" android:duration="@android:integer/config_mediumAnimTime" /> <rotate android:fromDegrees="0" android:toDegrees="180" android:pivotX="50%" android:pivotY="50%" /> </set>
Glide.with(this) .applyDefaultRequestOptions(ro) .load(productImage).transition(GenericTransitionOptions .with(R.anim.image_glide_animation)) .into(imgView);
You can define custom animation using ViewPropertyTransition.Animator
and apply it to image loading request as shown below.
ViewPropertyTransition.Animator rotationAnim = new ViewPropertyTransition.Animator() { @Override public void animate(View view) { ObjectAnimator rotation = ObjectAnimator.ofFloat(view, "rotation", 0f, 90f); rotation.setDuration(1000); rotation.start(); } }; Glide.with(this) .applyDefaultRequestOptions(ro) .load(productImage).transition(GenericTransitionOptions.with(rotationAnim)) .into(imgView);
How to add rounded corners to ImageView
RequestOptions glideOptions = new RequestOptions(); glideOptions.placeholder(R.drawable.powered_by_google_light); //glideOptions.transform(new RoundedCorners(15)); glideOptions.transforms(new CenterCrop(), new RoundedCorners(15)); Glide.with(activity).load(url).apply(glideOptions).into(iv);
Using Glide with Kotlin
Include the Glide dependencies, including the annotation processor:
dependencies { implementation 'com.github.bumptech.glide:glide:4.4.0' kapt 'com.github.bumptech.glide:compiler:4.4.0' }
Include the kotlin-kapt
plugin in your build.gradle file:
apply plugin: 'kotlin-kapt'
Create a AppGlideModule
implementation:
import com.bumptech.glide.annotation.GlideModule import com.bumptech.glide.module.AppGlideModule @GlideModule class AppGlideModule : AppGlideModule()
Build the project and then use the generated API:
GlideApp.with(this) .load(URL) .into(image)