Glide

1. What is Glide?

              Glide is an image loading framework developed by Bump Technologies that allows us to load and display images in an extremely simple way on the Android platform.  

    2. Dependency, network permissions:

       compile 'com.github.bumptech.glide:glide:3.7.0' //3.7 dependencies

       <uses-permission android:name="android.permission.INTERNET" /> network permissions

    3. Basic usage

        Glide.with(this).load(url).into(imageView);

        ①. What is the difference between Glide using the with parameter in Activity, Fragment, and Adapter?

             The instance passed in the with() method will determine the life cycle of Glide loading images. If an instance of Activity or Fragment is passed in, when the Activity or Fragment is destroyed, the image loading will also stop. If an ApplicationContext is passed in, the image loading will only stop when the application is killed. 

        ②. load() method

            This method is used to specify the image resource to be loaded. Glide supports loading a variety of image resources, including network images, local images, application resources, binary streams, Uri objects, and more. Therefore, the load() method also has many method overloads

            //Load local image:

            File file = new File(getExternalCacheDir()+"/image.jpg");

            Glide.with(this).load(file).into(imageView);

             // load application resources

            int resource = R.drawable.image;

            Glide.with(this).load(resource).into(imageView);

            // load binary stream

            byte[] image = getImageBytes();

            Glide.with(this).load(image).into(imageView);

            // Load Uri object

            Uri imageUri = getImageUri ();

            Glide.with(this).load(imageUri).into(imageView);

        ③.into() method

            The into() method is not only limited to accepting parameters of type ImageView

    4. Use

Glide.with(this)
                .load(url)//Load address
// .asGif()//Only dynamic images are allowed to be loaded, if static images are loaded, the loading will fail
                .asBitmap()//Only allow static images to be loaded
                .placeholder(R.mipmap.ic_launcher)//placeholder
                .error(R.mipmap.ic_launcher)//Exception placeholder map
                .diskCacheStrategy(DiskCacheStrategy.NONE)//Disable Glide's cache function.
                .override(100, 100)//Specify the image size
                .into(imageView);

   5. Source code analysis

    Before reading the Glide source code, we read the source code with the following questions, hoping to solve it in the process of reading the source code:

  1. What are Glide pictures used to download? HttpClient or HttpURLConnection? Or OKHttp?
  2. How are Glide images decoded? Is it the BitmapFactory.decodeXXX method we usually use?
  3. After Glide downloads the image, how does it load it into the ImageView?
  4. How does Glide implement caching? Is it LruCache and DiskLruCache?
  5. How are Glide threads managed? How many core threads? How many max threads? Is there a limit on the maximum number of tasks?
  6. How does Glide support Gifs? Is it through the Movie object?

   with() method

        The case of passing in the Application parameter:

            If an Application object is passed in the Glide.with() method, then the get() method overload with the Context parameter will be called here, and then the getApplicationManager() method will be called to obtain a RequestManager object. In fact, this is the simplest case, because the life cycle of the Application object is the life cycle of the application, so Glide does not need to do special processing, it is automatically synchronized with the life cycle of the application, if the application If closed, Glide's loading will also be terminated at the same time

        In the case of passing in non-Application parameters:

            Regardless of whether you pass in Activity, FragmentActivity, Fragment under the v4 package, or Fragment under the app package in the Glide.with() method, the final process is the same, that is, a hidden element will be added to the current Activity. Fragment. The specific logic added is in lines 117 and 141 of the above code, corresponding to the two Fragments in the app package and the v4 package, respectively. So why add a hidden Fragment here? Because Glide needs to know the lifetime of loading. A very simple reason, if you are loading an image on an Activity, and the Activity is closed by the user before the image is loaded, should the image continue to be loaded? Of course not. But Glide has no way to know the life cycle of Activity, so Glide uses the trick of adding hidden Fragment, because the life cycle of Fragment and Activity are synchronized, if Activity is destroyed, Fragment can be monitored, so Glide can catch this event and stop the image from loading.

            If we use Glide in a non-main thread, then no matter whether you pass in an Activity or a Fragment, it will be forced to be processed as an Application.

Summary: The with() method is actually just to get a RequestManager object, and then Glide will determine the life cycle of image loading according to the parameters we pass into the with() method

 

    load() method:

        Call the fromString() method, then call the load() method, and then pass in the incoming image URL address. The fromString() method is also very simple, that is, the loadGeneric() method is called, and the specified parameter is String.class, because the load() method passes in a string parameter, because it can be seen that most operations are performed in fromString () in the loadGeneric() method

      loadGeneric() calls Glide.buildStreamModelLoader() and Glide.buildFileDescriptorModelLoader() methods to get ModelLoader objects. The ModelLoader object is used to load pictures, and we pass different types of parameters to the load() method, and we will also get different ModelLoader objects here. Since the parameter we just passed in is String.class, we finally get a StreamStringLoader An object that implements the ModelLoader interface.

        The loadGeneric() method is to return a DrawableTypeRequest object, so at the end of the loadGeneric() method, a new DrawableTypeRequest object is added, and then the ModelLoader object just obtained and a lot of miscellaneous things are passed in

        DrawableTypeRequest    

        The main thing is that it provides two methods, asBitmap() and asGif(), which are used to force the loading of static images and dynamic images.

As can be seen from the source code, they have created a BitmapTypeRequest and a GifTypeRequest respectively. If there is no mandatory specification, DrawableTypeRequest is used by default.

        There is no load method in DrawableTypeRequest, so it is a method in the parent class

 

    into() method:

        

        

Introduction to Glide Cache

    There are two types of Glide caches:

        ①.Memory cache

            The main function of the memory cache is to prevent applications from repeatedly reading image data into memory

        ②. Disk cache

            The main function of the hard disk cache is to prevent applications from repeatedly downloading and reading data from the network or elsewhere

    Cache key:

        The fetcher.getId() method in the load() method in the Engine class     obtains an id string, which is the unique identifier of the image we want to load. For example, if it is an image on the Internet, then This id is the url address of this image     

       In the next line, this id is passed into the buildKey() method of EngineKeyFactory along with 10 parameters such as signature, width, height, etc., thereby constructing an EngineKey object, which is the cache key in Glide.

        It can be seen that there are many conditions for determining the cache key. Even if you use the override() method to change the width or height of the image, a completely different cache key will be generated.

 

memory cache

        With the cache key, the next step is to start caching, so let's start with the memory cache.

        First of all, you need to know that Glide automatically turns on memory caching by default. That is to say, when we use Glide to load an image, the image will be cached in memory. As long as it has not been cleared from memory, the next time we use Glide to load this image, it will be directly loaded from the memory. It can be read from memory instead of re-reading from the network or hard disk, which can undoubtedly greatly improve the loading efficiency of pictures. For example, if you swipe up and down in a RecyclerView repeatedly, as long as the images loaded by Glide in the RecyclerView can be quickly read and displayed directly from the memory, the user experience is greatly improved.

        The most user-friendly thing about Glide is that you don't even need to write any extra code to automatically enjoy this extremely convenient memory cache function, because Glide has it turned on by default.

    Disable caching:

        Glide.with(this) .load(url) .skipMemoryCache(true) .into(imageView);

 

    

hard disk cache

Glide.with(this)
     .load(url)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(imageView);

Call the diskCacheStrategy() method and pass in DiskCacheStrategy.NONE to disable Glide's hard disk caching.

The diskCacheStrategy() method is basically everything Glide's hard disk cache functions, and it accepts four parameters:

  • DiskCacheStrategy.NONE: Indicates that nothing is cached.
  • DiskCacheStrategy.SOURCE: Indicates that only original images are cached.
  • DiskCacheStrategy.RESULT: Indicates that only the converted images are cached (the default option).
  • DiskCacheStrategy.ALL : Indicates that both the original image and the converted image are cached.

 

Implement image preloading preload() :

Glide.with(this)
        .load(url)
        .diskCacheStrategy(DiskCacheStrategy.SOURCE)
        .preload();

    If the preload() method is used, it is best to specify the cache strategy of diskCacheStrategy as DiskCacheStrategy.SOURCE. Because the preload() method defaults to the preloaded original image size, and the into() method defaults to dynamically determine the size of the loaded image based on the size of the ImageView control. Therefore, if the cache strategy of diskCacheStrategy is not specified as DiskCacheStrategy.SOURCE, it is easy to cause the phenomenon that we use the into() method to load the image after the preloading is completed, but still request the image from the network.

        The source code of PreloadTarget is very simple. The obtain() method just creates a new instance of PreloadTarget, and the onResourceReady() method does nothing but calls the Glide.clear() method.

Glide.clear() here does not mean to clear the cache, but to indicate that the loading has been completed and the resources are released, so there is no need to be confused here.

 

 

The downloadOnly() method to access the cached file of the image is defined in the DrawableTypeRequest class :

     There are two method overloads, one receives the width and height of the image, and the other receives a generic object   

  • downloadOnly(int width, int height)
  • downloadOnly(Y target)

     These two methods have their own application scenarios, among which downloadOnly(int width, int height) is used to download pictures in the child thread, and downloadOnly(Y target) is used to download pictures in the main thread.

 

      Usage of downloadOnly(int width, int height) . When the downloadOnly(int width, int height) method is called, a FutureTarget object will be returned immediately, and then Glide will start downloading the image file in the background. Next, we call the get() method of FutureTarget to get the downloaded image file. If the image has not been downloaded at this time, the get() method will block, and will not return a value until the image is downloaded. .

      The hard disk cache strategy must be specified as DiskCacheStrategy.SOURCE or DiskCacheStrategy.ALL, otherwise Glide will not be able to use the image cache file we just downloaded.

 

listener() method

    

String url = "http://172.16.54.8:8080/test/zy.jpg";
Glide.with(this)
        .load(url)
        .listener(new RequestListener<String, GlideDrawable>() {
            @Override
            public boolean onException(Exception e, String model, Target<GlideDrawable> target,
                                       boolean isFirstResource) {
                return false;
            }

            @Override
            public boolean onResourceReady(GlideDrawable resource, String model,
                                           Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                return false;
            }
        })
        .into(simpleTarget);

            Both the onResourceReady() method and the onException() method have a return value of a boolean value. Returning false means that the event has not been processed and will continue to be passed down. Returning true means that the event has been processed, so it will not Continue to pass down again. For a simple example, if we return true in the RequestListener's onResourceReady() method, then the Target's onResourceReady() method will not be called back.

        The onResourceReady() method of requestListener will continue to call Target's onResourceReady() method only when the onResourceReady() method returns false, which is the implementation principle of the listener() method

        The onException() method of requestListener will continue to call the setErrorPlaceholder() method only if the onException() method returns false. That is to say, if we return true in the onException() method, the exception placeholder map set by the error(int resourceId) method in the Glide request is invalid.

 

 

dontTransform() method: Indicates that Glide does not perform image transformation during the process of loading the image

Glide.with(this)
        .load(url)
 .dontTransform()
 .into(imageView);

        There is a problem with using the dontTransform() method, that is, after calling this method, all image transformation operations are invalid. What if I have some image transformation operations that must be performed? Don't worry, there is always a way. In this case, we only need to use the override() method to force the image size to be specified as the original size. The code is as follows:

Glide.with(this)
        .load(url)
 .override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
 .into(imageView);

        Specify the width and height of the image as Target.SIZE_ORIGINAL through the override() method, the problem is also solved

 

 

Basic usage of image transformation

        The usage of adding image transformation is very simple. We only need to call the transform() method and pass the image transformation operation we want to perform as a parameter into the transform() method, as shown below:

Glide.with(this)
        .load(url)
 .transform(...)
 .into(imageView);

        As for the specific image transformation operation to be performed, this usually needs to be written by ourselves. However, Glide has built-in two image transformation operations, which we can use directly, one is CenterCrop and the other is FitCenter.

        But these two built-in image transformation operations do not actually need to use the transform() method. Glide directly provides ready-made APIs for our convenience:

Glide.with(this)
        .load(url)
        .centerCrop()
        .into(imageView);

Glide.with(this)
        .load(url)
        .fitCenter()
        .into(imageView);

 

public class CenterCrop extends BitmapTransformation {

    public CenterCrop(Context context) {
        super(context);
    }

    public CenterCrop(BitmapPool bitmapPool) {
        super(bitmapPool);
    }

    // Bitmap doesn't implement equals, so == and .equals are equivalent here.
    @SuppressWarnings("PMD.CompareObjectsWithEquals")
    @Override
    protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
        final Bitmap toReuse = pool.get(outWidth, outHeight, toTransform.getConfig() != null
                ? toTransform.getConfig() : Bitmap.Config.ARGB_8888);
        Bitmap transformed = TransformationUtils.centerCrop(toReuse, toTransform, outWidth, outHeight);
        if (toReuse != null && toReuse != transformed && !pool.put(toReuse)) {
            toReuse.recycle();
        }
        return transformed;
    }

    @Override
    public String getId() {
        return "CenterCrop.com.bumptech.glide.load.resource.bitmap";
    }
}

        CenterCrop is inherited from BitmapTransformation, which is the top priority, because the entire image transformation function is based on this inheritance structure.

        Next, the most important thing in CenterCrop is the transform() method, and we can ignore other methods for the time being. There are four parameters in the transform() method, each of which is very important, let's interpret them one by one. The first parameter pool, which is a Bitmap cache pool in Glide, is used to reuse Bitmap objects, otherwise it will consume a lot of memory to recreate Bitmap objects every time the image is transformed. The second parameter toTransform, this is the Bitmap object of the original image, we just want to transform it. The third and fourth parameters are relatively simple, representing the width and height of the image after transformation, which are actually the width and height values ​​passed in the override() method.

        The details of the transform() method. First, the first line tries to obtain a reusable Bitmap object from the Bitmap buffer pool, and then passes this object together with the toTransform, outWidth, and outHeight parameters into the TransformationUtils.centerCrop() method.

public final class TransformationUtils {

    public static Bitmap centerCrop(Bitmap recycled, Bitmap toCrop, int width, int height) {
        if (toCrop == null) {
            return null;
        } else if (toCrop.getWidth() == width && toCrop.getHeight() == height) {
            return toCrop;
        }
        // From ImageView/Bitmap.createScaledBitmap.
        final float scale;
        float dx = 0, dy = 0;
        Matrix m = new Matrix();
        if (toCrop.getWidth() * height > width * toCrop.getHeight()) {
            scale = (float) height / (float) toCrop.getHeight();
            dx = (width - toCrop.getWidth() * scale) * 0.5f;
        } else {
            scale = (float) width / (float) toCrop.getWidth();
            dy = (height - toCrop.getHeight() * scale) * 0.5f;
        }
        m.setScale(scale, scale);
        m.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));

        final Bitmap result;
        if (recycled != null) {
            result = recycled;
        } else {
            result = Bitmap.createBitmap(width, height, getSafeConfig(toCrop));
        }

        // We don't add or remove alpha, so keep the alpha setting of the Bitmap we were given.
        TransformationUtils.setAlpha(toCrop, result);

        Canvas canvas = new Canvas(result);
        Paint paint = new Paint(PAINT_FLAGS);
        canvas.drawBitmap(toCrop, m, paint);
        return result;
    }

}

        This code is the core code of the entire image transformation function. Do some verification first. If the original image is empty, or the size of the original image is the same as the target cropping size, then give up the cropping and calculate the scale of the canvas through mathematical calculations. The ratio and offset value of the . Crop the Bitmap object, crop the Bitmap object for drawing, and return the final result

        After getting the cropped Bitmap object, we go back to CenterCrop. You will see that before finally returning the Bitmap object, we will try to put the reused Bitmap object back into the cache pool, so that we can continue to use it next time.

 

 

skills: 

1.Glide.with(context).resumeRequests()和 Glide.with(context).pauseRequests()

When the list is sliding, call pauseRequests() to cancel the request, and when the sliding stops, call resumeRequests() to resume the request. Wouldn't that be better?

2.Glide.clear()

This method can help you when you want to clear all image load requests.

3.ListPreloader

If you want the list to be preloaded, try the ListPreloader class.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325197046&siteId=291194637