Android base development library to make development easier. DevRing & Demo address: github.com/LJYcoder/De…

Study/Reference address: https://blog.csdn.net/column/details/15318.html https://blog.csdn.net/u013005791/article/details/74532091 https://www.jianshu.com/p/325bd2f56ca7

preface

It’s been five months since the last installment, so while there’s no one out of work, write more and improve the series. Today we bring you the picture loading framework Glide use introduction. Here is the first guo God Glide series tutorial, with the source code is very detailed and clear. The following is a summary of the learning practice, not related to source code analysis, only related to usage. Glide is much lighter than Fresco, the API is simpler to call, and it is recommended if image loading is not very demanding. A comparison of Fresco and Glide can be found here

The version of Glide involved in this article is 4.x

introduce

As before, there are several modules to introduce: configure, load images, obtain Bitmap, download images, Generated API, obfuscating.

1. The configuration

1.1 Adding a Dependency

compile 'com. Making. Bumptech. Glide: glide: 4.4.0' 
annotationProcessor 'com. Making. Bumptech. Glide: the compiler: 4.4.0' // Annotation handler
Copy the code

1.2 Custom Modules

Custom modules include modifying default configurations and replacing components. This is done by inheriting the AppGlideModule class and overwriting the related methods. Remember to annotate the class with the @glidemodule annotation for Glide recognition. As follows:

@GlideModule
public class GlideConfigModule extends AppGlideModule {

    @Override
    public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
          // Modify the default configuration, such as cache configuration
    }

    @Override
    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
          // Replace components, such as network request components}}Copy the code

1.2.1 cache

Configure disk cache and memory cache in applyOption

@Override
public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
    // Disk cache configuration (default cache size: 250M, default stored in internal storage)
    // Set the disk cache to external storage and specify the cache size
    builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, diskCacheSize);
    // Set the disk cache to be stored in the specified directory and specify the cache size
    builder.setDiskCache(new DiskLruCacheFactory(new DiskLruCacheFactory.CacheDirectoryGetter() {
        @Override
        public File getCacheDirectory(a) {
            return diskCacheFolder;
        }
    }, diskCacheSize);

    // Memory cache configuration (not recommended, Glide will be allocated automatically according to the phone configuration)
    // Set the memory cache size
    builder.setMemoryCache(new LruResourceCache(memoryCacheSize));
    // Set the Bitmap pool size
    builder.setBitmapPool(new LruBitmapPool(bitmapPoolSize));
}
Copy the code

1.2.2 Replacing Components

For example, replace the network component with okHTTP. Add dependencies.

compile 'com. Squareup. Okhttp3: okhttp: 3.9.0'
compile 'com. Making. Bumptech. Glide: okhttp3 - integration: 4.3.1'
Copy the code

Its internal implementation is essentially a component replacement in registerComponents.

@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
     registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
}
Copy the code

Of course, there are many components that can be replaced, but there is generally no need for this.

//Glide default component
register(File.class, ParcelFileDescriptor.class, new FileDescriptorFileLoader.Factory());
register(File.class, InputStream.class, new StreamFileLoader.Factory());
register(int.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());
register(int.class, InputStream.class, new StreamResourceLoader.Factory());
register(Integer.class, ParcelFileDescriptor.class, new FileDescriptorResourceLoader.Factory());
register(Integer.class, InputStream.class, new StreamResourceLoader.Factory());
register(String.class, ParcelFileDescriptor.class, new FileDescriptorStringLoader.Factory());
register(String.class, InputStream.class, new StreamStringLoader.Factory());
register(Uri.class, ParcelFileDescriptor.class, new FileDescriptorUriLoader.Factory());
register(Uri.class, InputStream.class, new StreamUriLoader.Factory());
register(URL.class, InputStream.class, new StreamUrlLoader.Factory());
register(GlideUrl.class, InputStream.class, new HttpUrlGlideUrlLoader.Factory());
register(byte[].class, InputStream.class, newStreamByteArrayLoader.Factory()); .Copy the code

1.2.3 note

A project (including the main program and dependent libraries) can only exist in a custom inheritance AppGlideModule module, if there are multiple, will be submitted to the com. Android. Dex. DexException: Multiple dex files define Lcom/bumptech/glide/GeneratedAppGlideModuleImpl anomalies. However, multiple custom modules that inherit from LibraryGlideModule (used to override registerComponents for component replacement) are allowed.

2. Load the image

2.1 Common Operations

2.1.1 Loading images into ImageView

Glide.with(context)
        .load(url)
        .into(imageView);
Copy the code

The parameters of the with() method can be activities, fragments, etc. Will be used for the image loading lifecycle, such as when an activity is passed in, the associated image resources will be reclaimed when the activity is destroyed. The load() method can take String, Uri, File, resource ID, and so on. Into () can take ImageView, Target, and the width and height of the image.

2.1.2 Load an image into ImageView and specify a placeholder

RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(loadingResId) // Set the image to be displayed in the loading state
              .error(errorResId); // Set the image to be displayed in the "failed to load" state
Glide.with(context)
     .load(url)
     .apply(requestOptions)
     .into(imageView);
Copy the code

2.1.3 Load image to ImageView and specify cache policy

RequestOptions requestOptions = new RequestOptions();
requestOptions.skipMemoryCache(true) // Do not add memory cache, the default will be added
              .diskCacheStrategy(DiskCacheStrategy.NONE); // Do not add disk cache
Glide.with(context)
     .load(url)
     .apply(requestOptions)
     .into(imageView);
Copy the code

The disk cache policies are as follows: diskCacheStrategy. NONE: No content is cached. Diskcachestrategy. DATA: indicates that only raw images are cached. DiskCacheStrategy. RESOURCE: said only cache the image after the transformation. Diskcachestrategy. ALL: caching both the original image and the converted image. DiskCacheStrategy. AUTOMATIC: said to Glide resources according to the pictures intelligently choose to use which kind of caching strategy (the default option).

Two more points to add:

  1. The network image cache is stored according to THE URL address. For the same image but its URL address is different (changeable), it cannot play the role of cache. This can be handled by customizing urls, as described in the “Advanced Techniques” section here.
  2. Clearing cached data
// Clear the memory cache in the main thread
Glide.get(mContext).clearMemory();

// Clear the disk cache in a background thread
Glide.get(mContext).clearDiskCache();
Copy the code

####2.1.4 Load the image into ImageView and specify the image size

RequestOptions requestOptions = new RequestOptions();
requestOptions.override(300.200); // Set the size to 300*200, regardless of the imageView size
//requestOptions.override(Target.SIZE_ORIGINAL); // Set the image size to the original size, which has a higher OOM risk
Glide.with(context)
     .load(url)
     .apply(requestOptions)
     .into(imageView);
Copy the code

2.1.5 Load images to ImageView and configure transition animation

Glide.with(context)
     .load(url)
     .transition(DrawableTransitionOptions.withCrossFade(600))// For Drawable, transition animation lasts 600ms
/ /. The transition (BitmapTransitionOptions withCrossFade (600)) / / apply to the Bitmap, transition animations for 600 ms
/ /. The transition (GenericTransitionOptions. With (animationId)) / / apply to custom transition effects, the incoming animationId
     .into(imageView);
Copy the code

2.1.6 Load images to ImageView and add image transformation

Make sure you have added image transform library dependencies:

 compile 'jp. Wasabeef: glide - transformations: 3.1.1 @ aar'// Image conversion tool
Copy the code

Apply a single transform

RequestOptions requestOptions = new RequestOptions();
// Add rounded corner transform
requestOptions.transform(new RoundedCornersTransformation(radius, margin));
// Add a fuzzy transform
//requestOptions.transform(new BlurTransformation(blurRadius));
// Add the whiter transform
//requestOptions.transform(new GrayscaleTransformation());. Glide.with(context) .load(url) .apply(requestOptions) .into(imageView);Copy the code

Apply multiple transformations simultaneously

List<Transformation> list = new ArrayList<>();
list.add(new RoundedCornersTransformation(radius, margin));
list.add(new BlurTransformation(blurRadius));
list.add(new GrayscaleTransformation());
MultiTransformation multiTransformation = new MultiTransformation(list);
RequestOptions requestOptions = new RequestOptions();
// Apply rounded, blurred, and gray transform effects at the same time
requestOptions.transform(multiTransformation);
Glide.with(context)
     .load(url)
     .apply(requestOptions)
     .into(imageView);
Copy the code

More effective transformation see https://github.com/wasabeef/glide-transformations. Alternatively, you can disable image transformations with dontTransform().

RequestOptions requestOptions = new RequestOptions();
requestOptions.dontTransform();
Glide.with(context)
     .load(url)
     .apply(requestOptions)
     .into(imageView);
Copy the code

2.2 preload

Sometimes, for a smoother experience, you can use the preload feature to prepare the image and load it quickly when it’s ready for display.

Glide.with(context)
     .load(url)
     .preload();
Copy the code

2.3 Listening to the loading result

If you need to know the result of the load, you can use listener() to listen.

Glide.with(context)
     .load(url)
     .listener(new RequestListener<Drawable>() {
        @Override
        public boolean onLoadFailed(@Nullable GlideException e, Object model,     Target<Drawable> target, boolean isFirstResource) {
            // Load failed
            return false;
        }

        @Override
        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
            // The image was loaded successfully
            // If return true, Target's onResourceReady is no longer called, and the imageView will not display the loaded image.
            return false;
        }
     }).into(imageView);
Copy the code

3. Get the Bitmap

Sometimes we need to get the Bitmap back loaded. Here are two ways to do this.

3.1 Through listener()

Glide.with(context)
     .asBitmap() // The format is Bitmap
     .load(url)
     .listener(new RequestListener<Bitmap>() {
          @Override
          public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
              // Load failed
              return false;
          }
          @Override
          public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
              // The load succeeded. Resource is the loaded bitmap
              return false;
          }
      })
     .into(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);// Load the original image size
Copy the code

3.2 Implemented by SimpleTarget

Glide.with(context)
     .asBitmap()
     .load(url)
     .into(new SimpleTarget<Bitmap>() {
          @Override
          public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
                // The load succeeded. Resource is the loaded bitmap}});// This implementation will not be able to listen for load failures
Copy the code

4. Download pictures

Use the Submit () method to download the picture. Download the image and save it to the specified file:

public void downLoadImage(final Context context, final String url, final File targetFile, final ImageListener<File> imageListener) {
    if (cacheThreadPool == null) {
        cacheThreadPool = Executors.newCachedThreadPool();
    }

    cacheThreadPool.execute(new Runnable() {
        @Override
        public void run(a) {
            try {
                File sourceFile = Glide.with(context).asFile().load(url).submit().get();
                if(FileUtil.copyFile(sourceFile, targetFile) && imageListener ! =null) {
                    imageListener.onSuccess(targetFile);// Pass File through a callback, which is in the background thread}}catch (Exception exception) {
                if(imageListener ! =null) {
                    imageListener.onFail(exception);// Callback in background thread}}}}); }Copy the code

5. Generated API

New features introduced after Glide4.x.

5.1 Function 1: You can continue to chain-call loading like 3.x

The premise is that there needs to be a custom module in the project (see Section 1.2) that can then load images like 3.x

GlideApp.with(context)
        .load(url)
        .placeholder(R.mipmap.loading)
        .error(R.mipmap.error)
        .override(300.300)
        .transition(DrawableTransitionOptions.withCrossFade(600))
        .tranform(new GrayscaleTransformation())
        .skipMemoryCache(true)
        .diskCacheStrategy(DiskCacheStrategy.NONE)
        ....
        .into(imageView);
Copy the code

5.2 Function 2: Customize your API

Suppose now require each load pictures are open transition animations, every time can be loaded in. The transition (DrawableTransitionOptions. WithCrossFade (duration)), but each time to write such a long code is hard to avoid is not very convenient, This can be done by customizing the API. Customize a class for customizing the API. Requirements:

  1. Add the @glideExtension annotation above the class.
  2. Add @glideOption annotations above custom methods.
  3. The custom method must be static, and the first parameter must be RequestOptions, followed by as many parameters as you want to customize.
@GlideExtension
public class MyGlideExtension {
    private MyGlideExtension(a) {}@GlideOption
    public static void useTransition(RequestOptions options) {
        options.transition(DrawableTransitionOptions.withCrossFade(600))}}Copy the code

After the ReBuild project, the following calls can be made:

GlideApp.with(context)
        .load(url)
        .useTransition() // Use transition animation
        .into(imageView);
Copy the code

6. Confused

Add the following to the proGuard-rules. pro file for obfuscation configuration

# glide start - keep public class * implements com. Bumptech. Glide. The module. The AppGlideModule - keep public class implements com.bumptech.glide.module.LibraryGlideModule -keep class com.bumptech.glide.** { *; } -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** { **[] $VALUES; public *; } # glide overCopy the code