Android Glide use puzzle: why your image caching function does not work?

Android Glide use puzzle: why your image caching function does not work?

Preface

  • Glide, This function is very powerful Androidimage loading believe we are not familiar open-source framework

  • Because of its powerful functions, its source code is very complicated, which causes many people to stay away.

  • Try to Glidefunction decomposition, and source code analysis separately for each function, thereby reducing the Glidecomplexity of the source code.

    Next, I will launch a series on Glidefunctional analysis of the source code, are interested can continue to focus on

  • Today, I will mainly explain Glidethe problem when using the cache function: why Glide's cache does not work, I hope you will like it.

Please read the article Android source code analysis: take you to analyze the cache function of Glide first


1. Background

  • GlideThe realization of memory & disk caching is based Keyon the unique identification of the image cache
  • In order to reduce costs and security, developers often store pictures on cloud servers
    Such as Qiniuyun and so on.
  • In order to protect the customer's picture resources, the picture cloud server will Urladd a token parameter to the picture address
http://url.com/image.jpg?token=a6cvva6b02c670b0a 
  • GlideWhen loading the picture will be used plus the tokenparameters of the picture Urladdress as
    idparameters to generate the cache Key

2. Problem

  • As the tokenparameters of identity authentication may change, not static
  • If tokenparameters have changed, the picture Urlchange along, then generate the required id parameter cache key changes that cache Key changes will follow
  • This led to the same picture, but because of tokenparameter changes, which led to a change in Key cache, so that the Glidecache function failure

    The cache key has changed, that is, the current cache key of the same picture is different from the key previously written to the cache, which means that the previous cache cannot be found based on the current cache key when reading the cache, thus making it invalid


3. Solution

3.1 Principle

In generating the cache Keybefore id parameter, with the tokenpicture parameter of Urlthe address remove tokenparameters to the initial images Urlto generate the cache address Keyid parameter

KeyThe id parameter of the cache of a picture is always unique, which is equal to the picture Urladdress

3.2 Reserve knowledge: the logic of generating the id parameter of the cache key

Generating a cache Keyof idlogical parameters are: the picture directly to the URLaddress buffer as a Key idParameter

Look back at the article Android source code analysis: take you to analyze Glide's cache function to generate cache Keycode

public class Engine implements EngineJobListener,
        MemoryCache.ResourceRemovedListener,
        EngineResource.ResourceListener {

    public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,
            DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,
            Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {
        Util.assertMainThread();
        long startTime = LogTime.getLogTime();

        final String id = fetcher.getId();
       // id 
       // id =  url 
       //fetcher = HttpUrlFetcher HttpUrlFetcher.getid ->> 19

        EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),transcoder, loadProvider.getSourceEncoder());
       // id   signature width height 10 Key EngineKey 
       // equals()   hashCode() EngineKey EngineKey 
      // EngineKey  Glide Key

        ...
}


<--  19 getId() -->
public class HttpUrlFetcher implements DataFetcher<InputStream> {
    ...

    private final GlideUrl glideUrl;
   //GlideUrl =      2 load() url Glide url GlideUrl 

    @Override
    public String getId() {
        return glideUrl.getCacheKey();
       //->> 20
}

<--  20 getCacheKey()  -->

public class GlideUrl {

    private final URL url;
    private final String stringUrl;
    ...

   //GlideUrl 
     public GlideUrl(URL url) {
        this(url, Headers.DEFAULT);
    }

    public GlideUrl(String url) {
        this(url, Headers.DEFAULT);
    }


    public String getCacheKey() {
        return stringUrl != null ? stringUrl : url.toString();
       // GlideUrl 
       // URL 
       // URL toString() 

    }

    ...
}
 

3.3 Implementation scheme

That we simply rewrite getCacheKey()& the pictures with a token parameter Urladdress removed token parameter.

/**
  *  GlideUrl  &  getCacheKey()
  **/
   //1.  GlideUrl 
    public class mGlideUrl extends GlideUrl {

        private String mUrl;

       //     token Url  
        public MyGlideUrl(String url) {
            super(url);
            mUrl = url;
        }

       //2.  getCacheKey()
        @Override
        public String getCacheKey() {
            return mUrl.replace(deleteToken(), "");
           //  deleteToken()    token Url    token 
           // token URL 
           //->> 1
        }

       // 1 deleteToken()
        private String deleteToken() {
            String tokenParam = "";
            int tokenKeyIndex = mUrl.indexOf("?token=") >= 0 ? mUrl.indexOf("?token=") : mUrl.indexOf("&token=");
            if (tokenKeyIndex != -1) {
                int nextAndIndex = mUrl.indexOf("&", tokenKeyIndex + 1);
                if (nextAndIndex != -1) {
                    tokenParam = mUrl.substring(tokenKeyIndex + 1, nextAndIndex + 1);
                } else {
                    tokenParam = mUrl.substring(tokenKeyIndex);
                }
            }
            return tokenParam;
        }

    }

/**
  *  load()  mGlideUrl 
  **/

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

   // a.  url GlideUrl 
   //   b.  url key Id token 
 

4. Summary


Bangding/Like the comment! Because your encouragement is my biggest motivation for writing!