zoukankan      html  css  js  c++  java
  • Android的媒体管理框架:Glide

    Glide是一个高效、开源、 Android设备上的媒体管理框架,它遵循BSD、MIT以及Apache 2.0协议发布。Glide具有获取、解码和展示视频剧照、图片、动画等功能,它还有灵活的API,这些API使开发者能够将Glide应用在几乎任何网络协议栈里。创建Glide的主要目的有两个,一个是实现平滑的图片列表滚动效果,另一个是支持远程图片的获取、大小调整和展示。近日,Glide 3.0发布,现已提供jar包下载,同时还支持使用Gradle以及Maven进行构建。该版本包括很多值得关注的新功能,如支持Gif 动画和视频剧照解码、智能的暂停和重新开始请求、支持缩略图等,具体新增功能如下如下:GIF动画的解码:通过调用Glide.with(context).load(“图片路径“)方法,GIF动画图片可以自动显示为动画效果。如果想有更多的控制,还可以使用Glide.with(context).load(“图片路径“).asBitmap()方法加载静态图片,使用Glide.with(context).load(“图片路径“).asGif()方法加载动画图片



    1.本地视频剧照的解码:通过调用Glide.with(context).load(“图片路径“)方法,Glide能够支持Android设备中的所有视频剧照的加载和展示

    2.缩略图的支持:为了减少在同一个view组件里同时加载多张图片的时间,可以调用Glide.with(context).load(“图片路径“).thumbnail(“缩略比例“).into(“view组件“)方法加载一个缩略图,还可以控制thumbnail()中的参数的大小,以控制显示不同比例大小的缩略图

    3.Activity生命周期的集成:当Activity暂停和重启时,Glide能够做到智能的暂停和重新开始请求,并且当Android设备的连接状态变化时,所有失败的请求能够自动重新请求
    4.转码的支持:Glide的toBytes() 和transcode() 两个方法可以用来获取、解码和变换背景图片,并且transcode() 方法还能够改变图片的样式
    5.动画的支持:新增支持图片的淡入淡出动画效果(调用crossFade()方法)和查看动画的属性的功能
    6.OkHttp和Volley的支持:默认选择HttpUrlConnection作为网络协议栈,还可以选择OkHttp和Volley作为网络协议

    7.其他功能:如在图片加载过程中,使用Drawables对象作为占位符、图片请求的优化、图片的宽度和高度可重新设定、缩略图和原图的缓存等功能

    Glide.class

    利用这个方法可以获得一个RequestManager对象.

    RequestManager.class

    这个类主要是用来处理低内存的时候的处理;管理请求,比如请求的开始,暂停,结束;还有通过加载方法获得一个DrawableTypeRequest对象。

    低内存处理方法:

    管理请求的方法:与activity或者fragment的生命周期同步。

    加载的方法:

    load方法都是设置了一个泛型,最后都调用了:

    DrawableRequestBuilder.class

    [html] view plain copy
     
    1. @Override  
    2.    public DrawableRequestBuilder<ModelType> load(ModelType model) {  
    3.        super.load(model);  
    4.        return this;  
    5.    }  

    接着调用了GenericRequestBuilder类里面的方法,就是设置加载的参数到GenericRequestBuilder的this.model里:

    GenericRequestBuilder.class

    [html] view plain copy
     
    1. public GenericRequestBuilder<ModelType, DataType, ResourceType, TranscodeType> load(ModelType model) {  
    2.        this.model = model;  
    3.        isModelSet = true;  
    4.        return this;  
    5.    }  

    这里接触了两个类,一个是GenericRequestBuilder,一个是DrawableRequestBuilder。

    由GenericRequestBuilder得四种泛型参数可以看出, 这个类提供了加载各种资源的方法,是各种资源请求构建类的父类:

    通过以上方法来加载缩略图。

    第一个是对原数据的解码。

    第二个是对磁盘缓存的数据进行解码。

    第三个是对请求的数据进行编码,然后存到缓存里,之后从缓存中拿出的时候要通过解码。

    设置磁盘缓存的内容,DiskCacheStrategy类是个枚举类,他提供了四个参数:

    [html] view plain copy
     
    1. /** Caches with both {@link #SOURCE} and {@link #RESULT}. */  
    2.     ALL(true, true),  
    3.     /** Saves no data to cache. */  
    4.     NONE(false, false),  
    5.     /** Saves just the original data to cache. */  
    6.     SOURCE(true, false),  
    7.     /** Saves the media item after all transformations to cache. */  
    8.     RESULT(false, true);  

    all:缓存源资源和转换后的资源

    none:不作任何磁盘缓存

    source:缓存源资源

    result:缓存转换后的资源

    [html] view plain copy
     
    1. priority(Priority priority)  

    设置当次请求的优先级。

    [html] view plain copy
     
    1. transform(Transformation<ResourceType>... transformations)  

    设置对资源进行转换的接口:

    对于加载一般的图片到Imageview中,默认提供了CenterCrop和FitCenter两种实现。

    [html] view plain copy
     
    1. dontTransform()  

    移除当前的转换。

    [html] view plain copy
     
    1. transcoder(ResourceTranscoder<ResourceType, TranscodeType> transcoder)  

    设置资源加载完成后的动画,不包括从内存缓存中获取。

    [html] view plain copy
     
    1. dontAnimate()  

    移除设置的动画。

    [html] view plain copy
     
    1. placeholder(int resourceId)  
    2. placeholder(Drawable drawable)  

    设置加载的时候的图片。

    [html] view plain copy
     
    1. error(int resourceId)  
    2. error(Drawable drawable)  

    设置加载失败后显示的图片

    [html] view plain copy
     
    1. listener(RequestListener<? super ModelType, TranscodeType> requestListener)  

    设置加载监听。

    这个监听接口中有两个回调方法:

    [html] view plain copy
     
    1. skipMemoryCache(boolean skip)  

    设置是否跳过内存缓存。

    [html] view plain copy
     
    1. override(int width, int height)  

    设置加载资源图片的像素宽高。

    [html] view plain copy
     
    1. signature(Key signature)  
    [html] view plain copy
     
    1. load(ModelType model)  

    设置要加载的内容。

    通过上面的方法开启加载,中间的方法直接加载到view上,前后的方法用于预加载。

    预加载,真正调用的是上面的两个into方法。

    接着看子类DrawableRequestBuilder里面特有的方法:

    DrawableRequestBuilder类不仅继承了父类GenericRequestBuilder里面的方法,还显示了BitmapOptions和DrawableOptions两个接口:

    一个是控制bitmap的显示的位置或者大小(就是bitmap的转换),一个是控制图片显示出来时候的动画效果(不包括从内存中获取的图片资源)。接着看这些方法的具体实现:

    [html] view plain copy
     
    1. public DrawableRequestBuilder<ModelType> centerCrop() {  
    2.        return transform(glide.getDrawableCenterCrop());  
    3.    }  
    [html] view plain copy
     
    1. public DrawableRequestBuilder<ModelType> fitCenter() {  
    2.         return transform(glide.getDrawableFitCenter());  
    3.     }  

    将Glide中两个BitmapTransformation进行包装后,通过间接调用父类的transform设置到父类的transformation属性中。

    [html] view plain copy
     
    1. public final DrawableRequestBuilder<ModelType> crossFade() {  
    2.         super.animate(new DrawableCrossFadeFactory<GlideDrawable>());  
    3.         return this;  
    4.     }  

    而设置淡入淡出效果其实是设置了默认动画实现的DrawableCrossFadeFactory类到父类animationFactory属性中。

    [html] view plain copy
     
    1. public <Y extends Target<TranscodeType>> Y into(Y target) {  
    2.        Util.assertMainThread();  
    3.        if (target == null) {  
    4.            throw new IllegalArgumentException("You must pass in a non null Target");  
    5.        }  
    6.        if (!isModelSet) {  
    7.            throw new IllegalArgumentException("You must first set a model (try #load())");  
    8.        }  
    9.   
    10.        Request previous = target.getRequest();  
    11.   
    12.        if (previous != null) {  
    13.            previous.clear();  
    14.            requestTracker.removeRequest(previous);  
    15.            previous.recycle();  
    16.        }  
    17.   
    18.        Request request = buildRequest(target);  
    19.        target.setRequest(request);  
    20.        lifecycle.addListener(target);  
    21.        requestTracker.runRequest(request);  
    22.   
    23.        return target;  
    24.    }  

    这里构建好request的是个GenericRequest类型,然后就通过requestTracker.runRequest(request);来调用GenericRequest里的begin方法:

    [html] view plain copy
     
    1. @Override  
    2.   public void begin() {  
    3.       startTime = LogTime.getLogTime();  
    4.       if (model == null) {  
    5.           onException(null);  
    6.           return;  
    7.       }  
    8.   
    9.       status = Status.WAITING_FOR_SIZE;  
    10.       if (Util.isValidDimensions(overrideWidth, overrideHeight)) {  
    11.           onSizeReady(overrideWidth, overrideHeight);  
    12.       } else {  
    13.           target.getSize(this);  
    14.       }  
    15.   
    16.       if (!isComplete() && !isFailed() && canNotifyStatusChanged()) {  
    17.           target.onLoadStarted(getPlaceholderDrawable());  
    18.       }  
    19.       if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    20.           logV("finished run method in " + LogTime.getElapsedMillis(startTime));  
    21.       }  
    22.   }  

    这里的target.getSize(this);最终也是调用onSizeReady()方法:

    [html] view plain copy
     
    1. public void onSizeReady(int width, int height) {  
    2.        if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    3.            logV("Got onSizeReady in " + LogTime.getElapsedMillis(startTime));  
    4.        }  
    5.        if (status != Status.WAITING_FOR_SIZE) {  
    6.            return;  
    7.        }  
    8.        status = Status.RUNNING;  
    9.   
    10.        width = Math.round(sizeMultiplier * width);  
    11.        height = Math.round(sizeMultiplier * height);  
    12.   
    13.        ModelLoader<A, TmodelLoader = loadProvider.getModelLoader();  
    14.        final DataFetcher<TdataFetcher = modelLoader.getResourceFetcher(model, width, height);  
    15.   
    16.        if (dataFetcher == null) {  
    17.            onException(new Exception("Got null fetcher from model loader"));  
    18.            return;  
    19.        }  
    20.        ResourceTranscoder<Z, Rtranscoder = loadProvider.getTranscoder();  
    21.        if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    22.            logV("finished setup for calling load in " + LogTime.getElapsedMillis(startTime));  
    23.        }  
    24.        loadedFromMemoryCache = true;  
    25.        loadStatus = engine.load(signature, width, height, dataFetcher, loadProvider, transformation, transcoder,  
    26.                priority, isMemoryCacheable, diskCacheStrategy, this);  
    27.        loadedFromMemoryCache = resource != null;  
    28.        if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    29.            logV("finished onSizeReady in " + LogTime.getElapsedMillis(startTime));  
    30.        }  
    31.    }  

    接着调用了Engine类的load方法,这个类就是加载数据的引擎类:

    [html] view plain copy
     
    1. public <T, Z, R> LoadStatus load(Key signature, int width, int height, DataFetcher<T> fetcher,  
    2.            DataLoadProvider<T, Z> loadProvider, Transformation<Z> transformation, ResourceTranscoder<Z, R> transcoder,  
    3.            Priority priority, boolean isMemoryCacheable, DiskCacheStrategy diskCacheStrategy, ResourceCallback cb) {  
    4.        Util.assertMainThread();  
    5.        long startTime = LogTime.getLogTime();  
    6.   
    7.        final String id = fetcher.getId();  
    8.        EngineKey key = keyFactory.buildKey(id, signature, width, height, loadProvider.getCacheDecoder(),  
    9.                loadProvider.getSourceDecoder(), transformation, loadProvider.getEncoder(),  
    10.                transcoder, loadProvider.getSourceEncoder());  
    11.   
    12.        EngineResource<?cached = loadFromCache(key, isMemoryCacheable);  
    13.        if (cached != null) {  
    14.            cb.onResourceReady(cached);  
    15.            if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    16.                logWithTimeAndKey("Loaded resource from cache", startTime, key);  
    17.            }  
    18.            return null;  
    19.        }  
    20.   
    21.        EngineResource<?active = loadFromActiveResources(key, isMemoryCacheable);  
    22.        if (active != null) {  
    23.            cb.onResourceReady(active);  
    24.            if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    25.                logWithTimeAndKey("Loaded resource from active resources", startTime, key);  
    26.            }  
    27.            return null;  
    28.        }  
    29.   
    30.        EngineJob current = jobs.get(key);  
    31.        if (current != null) {  
    32.            current.addCallback(cb);  
    33.            if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    34.                logWithTimeAndKey("Added to existing load", startTime, key);  
    35.            }  
    36.            return new LoadStatus(cb, current);  
    37.        }  
    38.   
    39.        EngineJob engineJob = engineJobFactory.build(key, isMemoryCacheable);  
    40.        DecodeJob<T, Z, RdecodeJob = new DecodeJob<T, Z, R>(key, width, height, fetcher, loadProvider, transformation,  
    41.                transcoder, diskCacheProvider, diskCacheStrategy, priority);  
    42.        EngineRunnable runnable = new EngineRunnable(engineJob, decodeJob, priority);  
    43.        jobs.put(key, engineJob);  
    44.        engineJob.addCallback(cb);  
    45.        engineJob.start(runnable);  
    46.   
    47.        if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    48.            logWithTimeAndKey("Started new load", startTime, key);  
    49.        }  
    50.        return new LoadStatus(cb, engineJob);  
    51.    }  

    这个方法会先从内存缓存中去获取,没有就构建一个EngineJob引擎任务类,这个类会将一个任务(runnable对象)提交到线程池中,然后线程池经过一系列的调度,调用了EngineRunnable对象的run方法:

    [html] view plain copy
     
    1. public void run() {  
    2.     if (isCancelled) {  
    3.         return;  
    4.     }  
    5.   
    6.     Exception exception = null;  
    7.     Resource<?resource = null;  
    8.     try {  
    9.         resource = decode();  
    10.     } catch (Exception e) {  
    11.         if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    12.             Log.v(TAG, "Exception decoding", e);  
    13.         }  
    14.         exception = e;  
    15.     }  
    16.   
    17.     if (isCancelled) {  
    18.         if (resource != null) {  
    19.             resource.recycle();  
    20.         }  
    21.         return;  
    22.     }  
    23.   
    24.     if (resource == null) {  
    25.         onLoadFailed(exception);  
    26.     } else {  
    27.         onLoadComplete(resource);  
    28.     }  
    29. }  

    这里的decode()方法会先从磁盘缓存中去取数据,如果没有就源资源(网络中下载的资源)中获取:

    [html] view plain copy
     
    1. private Resource<?> decode() throws Exception {  
    2.        if (isDecodingFromCache()) {  
    3.            return decodeFromCache();  
    4.        } else {  
    5.            return decodeFromSource();  
    6.        }  
    7.    }  

    1.首先来看从磁盘缓存中获取资源:

    [html] view plain copy
     
    1. private Resource<?> decodeFromCache() throws Exception {  
    2.        Resource<?result = null;  
    3.        try {  
    4.            result = decodeJob.decodeResultFromCache();  
    5.        } catch (Exception e) {  
    6.            if (Log.isLoggable(TAG, Log.DEBUG)) {  
    7.                Log.d(TAG, "Exception decoding result from cache: " + e);  
    8.            }  
    9.        }  
    10.   
    11.        if (result == null) {  
    12.            result = decodeJob.decodeSourceFromCache();  
    13.        }  
    14.        return result;  
    15.    }  

    这里有两个方法:第一个,decodeJob.decodeResultFromCache(),如果设置缓存的是DiskCacheStrategy.RESULT,那么磁盘缓存中缓存的是transformed后的结果,所以就会调用该方法:

    [html] view plain copy
     
    1. public Resource<Z> decodeResultFromCache() throws Exception {  
    2.       if (!diskCacheStrategy.cacheResult()) {  
    3.           return null;  
    4.       }  
    5.   
    6.       long startTime = LogTime.getLogTime();  
    7.       Resource<Ttransformed = loadFromCache(resultKey);  
    8.       if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    9.           logWithTimeAndKey("Decoded transformed from cache", startTime);  
    10.       }  
    11.       startTime = LogTime.getLogTime();  
    12.       Resource<Zresult = transcode(transformed);  
    13.       if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    14.           logWithTimeAndKey("Transcoded transformed from cache", startTime);  
    15.       }  
    16.       return result;  
    17.   }  

    这里首先通过loadFromCache(resultKey)方法从磁盘缓存文件中decode已经经过transformed的资源(默认是使用UnitTransformation,在这里面没有做任何的资源转换),然后调用transcode(transformed)方法:该方法是把从磁盘decode出来的资源通过transcoder.transcode(transformed)来进行转换(这个方法是用来转换资源的类型用的,默认是使用UnitTranscoder,没有做任何操作)

    第二个,decodeJob.decodeSourceFromCache(),如果设置缓存的是DiskCacheStrategy.SOURCE,那么磁盘缓存中缓存的是原始数据,所以就会调用该方法:

    [html] view plain copy
     
    1. public Resource<Z> decodeSourceFromCache() throws Exception {  
    2.         if (!diskCacheStrategy.cacheSource()) {  
    3.             return null;  
    4.         }  
    5.   
    6.         long startTime = LogTime.getLogTime();  
    7.         Resource<Tdecoded = loadFromCache(resultKey.getOriginalKey());  
    8.         if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    9.             logWithTimeAndKey("Decoded source from cache", startTime);  
    10.         }  
    11.         return transformEncodeAndTranscode(decoded);  
    12.     }  

    这里首先从磁盘缓存中decode原数据,然后再调用transformEncodeAndTranscode(decoded)方法先进行transform,transform后会通过writeTransformedToCache(transformed);将经过转换的资源存入磁盘缓存,然后再进行transcode:

    [html] view plain copy
     
    1. private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {  
    2.        long startTime = LogTime.getLogTime();  
    3.        Resource<Ttransformed = transform(decoded);  
    4.        if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    5.            logWithTimeAndKey("Transformed resource from source", startTime);  
    6.        }  
    7.   
    8.        writeTransformedToCache(transformed);  
    9.   
    10.        startTime = LogTime.getLogTime();  
    11.        Resource<Zresult = transcode(transformed);  
    12.        if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    13.            logWithTimeAndKey("Transcoded transformed from source", startTime);  
    14.        }  
    15.        return result;  
    16.    }  

    2.再来看从源资源获取资源:

    [html] view plain copy
     
    1. private Resource<?> decodeFromSource() throws Exception {  
    2.         return decodeJob.decodeFromSource();  
    3.     }  
    [html] view plain copy
     
    1. public Resource<Z> decodeFromSource() throws Exception {  
    2.        Resource<Tdecoded = decodeSource();  
    3.        return transformEncodeAndTranscode(decoded);  
    4.    }  

    这里调用了decodeSource(),这个方法是从网络中获取data资源:

    [html] view plain copy
     
    1. private Resource<T> decodeSource() throws Exception {  
    2.        Resource<Tdecoded = null;  
    3.        try {  
    4.            long startTime = LogTime.getLogTime();  
    5.            final A data = fetcher.loadData(priority);  
    6.            if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    7.                logWithTimeAndKey("Fetched data", startTime);  
    8.            }  
    9.            if (isCancelled) {  
    10.                return null;  
    11.            }  
    12.            decoded = decodeFromSourceData(data);  
    13.        } finally {  
    14.            fetcher.cleanup();  
    15.        }  
    16.        return decoded;  
    17.    }  

    获取到网络资源后调用decodeFromSourceData(data)方法:

    [html] view plain copy
     
    1. private Resource<T> decodeFromSourceData(A data) throws IOException {  
    2.         final Resource<T> decoded;  
    3.         if (diskCacheStrategy.cacheSource()) {  
    4.             decoded = cacheAndDecodeSourceData(data);  
    5.         } else {  
    6.             long startTime = LogTime.getLogTime();  
    7.             decoded = loadProvider.getSourceDecoder().decode(data, width, height);  
    8.             if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    9.                 logWithTimeAndKey("Decoded from source", startTime);  
    10.             }  
    11.         }  
    12.         return decoded;  
    13.     }  

    这个方法里通过diskCacheStrategy.cacheSource()判断资源是否是将源数据保存在磁盘里,如果是则会调用cacheAndDecodeSourceData(A data):

    [html] view plain copy
     
    1. private Resource<T> cacheAndDecodeSourceData(A data) throws IOException {  
    2.         long startTime = LogTime.getLogTime();  
    3.         SourceWriter<Awriter = new SourceWriter<A>(loadProvider.getSourceEncoder(), data);  
    4.         diskCacheProvider.getDiskCache().put(resultKey.getOriginalKey(), writer);  
    5.         if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    6.             logWithTimeAndKey("Wrote source to cache", startTime);  
    7.         }  
    8.   
    9.         startTime = LogTime.getLogTime();  
    10.         Resource<Tresult = loadFromCache(resultKey.getOriginalKey());  
    11.         if (Log.isLoggable(TAG, Log.VERBOSE) && result != null) {  
    12.             logWithTimeAndKey("Decoded source from cache", startTime);  
    13.         }  
    14.         return result;  
    15.     }  

    这里先将原数据保存在磁盘缓存里,然后再decode出来。

    但是如果不需要保存源数据,就直接decode源数据:

    [html] view plain copy
     
    1. private Resource<T> decodeFromSourceData(A data) throws IOException {  
    2.        final Resource<T> decoded;  
    3.        if (diskCacheStrategy.cacheSource()) {  
    4.            decoded = cacheAndDecodeSourceData(data);  
    5.        } else {  
    6.            long startTime = LogTime.getLogTime();  
    7.            decoded = loadProvider.getSourceDecoder().decode(data, width, height);  
    8.            if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    9.                logWithTimeAndKey("Decoded from source", startTime);  
    10.            }  
    11.        }  
    12.        return decoded;  
    13.    }  

    decodeSource()方法执行完之后,接着执行transformEncodeAndTranscode(decoded):

    [html] view plain copy
     
    1. private Resource<Z> transformEncodeAndTranscode(Resource<T> decoded) {  
    2.        long startTime = LogTime.getLogTime();  
    3.        Resource<Ttransformed = transform(decoded);  
    4.        if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    5.            logWithTimeAndKey("Transformed resource from source", startTime);  
    6.        }  
    7.   
    8.        writeTransformedToCache(transformed);  
    9.   
    10.        startTime = LogTime.getLogTime();  
    11.        Resource<Zresult = transcode(transformed);  
    12.        if (Log.isLoggable(TAG, Log.VERBOSE)) {  
    13.            logWithTimeAndKey("Transcoded transformed from source", startTime);  
    14.        }  
    15.        return result;  
    16.    }  

    这里是将直接从源数据decode出来资源后,经过transform的转换,然后将transform后的资源存进磁盘缓存,然后在经过transcode方法来进行资源类型的转换(默认是使用UnitTranscoder,没有做任何操作)。还是提供逻辑图,一目了然吧:

    这个是基本流程图:

    使用方法:

    1.设置的不是imageview,可以用SimpleTarget来接受,然后在回调里面设置view的现实(但是缺少目标view的设置,似乎在列表中会出现错乱)

    [html] view plain copy
     
    1. Glide.with(StaggeredGridViewDemo.this).load(mImages.get(arg0).getPic()).asBitmap().override(250, 250).into(new SimpleTarget<Bitmap>() {  
    2.   
    3.                 @Override  
    4.                 public void onResourceReady(Bitmap arg0, GlideAnimation<? super Bitmap> arg1) {  
    5.                     Log.i("llj", "arg0.getWidth()+arg0.getHeight()" + arg0.getWidth() + arg0.getHeight());  
    6.                      holder.textView.setBackgroundDrawable(new BitmapDrawable(arg0));  
    7.                 }  
    8.             });  

    但是override(250, 250)方法没有起作用:

    也可以通过SimpleTarget的构造函数传参数:

    [html] view plain copy
     
    1. Glide.with(StaggeredGridViewDemo.this).load(mImages.get(arg0).getPic()).asBitmap().into(new SimpleTarget<Bitmap>(250, 250) {  
    2.   
    3.                 @Override  
    4.                 public void onResourceReady(Bitmap arg0, GlideAnimation<? super Bitmap> arg1) {  
    5.                     Log.i("llj", "arg0.getWidth()+arg0.getHeight()" + arg0.getWidth() + ";" + arg0.getHeight());  
    6.                     // holder.textView.setBackgroundDrawable(new BitmapDrawable(arg0));  
    7.                 }  
    8.             });  


    但是SimpleTarget的构造函数穿进去的参数也没有起作用:

    2.设置预加载:(可以提前将资源加载到磁盘缓存中,默认的缓存目录是datadata下的250M空间,自己可以根据需求更改)

    [html] view plain copy
     
    1. final PreloadTarget<Bitmaptarget = PreloadTarget.obtain(250, 250);  
    2.             Glide.with(StaggeredGridViewDemo.this).load(mImages.get(arg0).getPic()).asBitmap().listener(new RequestListener<String, Bitmap>() {  
    3.   
    4.                 @Override  
    5.                 public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {  
    6.   
    7.                     return false;  
    8.                 }  
    9.   
    10.                 @Override  
    11.                 public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {  
    12.                     Log.i("llj", "arg0.getWidth()+arg0.getHeight()" + resource.getWidth() + resource.getHeight());  
    13.                     return false;  
    14.                 }  
    15.             }).into(target);  

    这里在PreloadTarget中设置的像素的缩放还是没有用:

    [html] view plain copy
     
    1. final PreloadTarget<Bitmaptarget = PreloadTarget.obtain(0, 0);  
    2.             Glide.with(StaggeredGridViewDemo.this).load(mImages.get(arg0).getPic()).asBitmap().override(250, 250).listener(new RequestListener<String, Bitmap>() {  
    3.   
    4.                 @Override  
    5.                 public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {  
    6.   
    7.                     return false;  
    8.                 }  
    9.   
    10.                 @Override  
    11.                 public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {  
    12.                     Log.i("llj", "arg0.getWidth()+arg0.getHeight()" + resource.getWidth() + resource.getHeight());  
    13.                     return false;  
    14.                 }  
    15.             }).into(target);  

    这里在override(250, 250)设置依然没有作用:

    3.加载到imageview上

    [html] view plain copy
     
    1. Glide.with(StaggeredGridViewDemo.this).load(mImages.get(arg0).getPic()).asBitmap().override(250, 250).listener(new RequestListener<String, Bitmap>() {  
    2.   
    3.                 @Override  
    4.                 public boolean onException(Exception e, String model, Target<Bitmap> target, boolean isFirstResource) {  
    5.   
    6.                     return false;  
    7.                 }  
    8.   
    9.                 @Override  
    10.                 public boolean onResourceReady(Bitmap resource, String model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {  
    11.                     Log.i("llj", "arg0.getWidth()+arg0.getHeight()" + resource.getWidth() + resource.getHeight());  
    12.                     return false;  
    13.                 }  
    14.             }).into(holder.imageview);  

    拿到的Bitmap的宽高经过了转换,但转换后的比例并不是250:250:

    但是如果设置了centerCrop():

    而用Picasso转换后的图片是250:250:

    [html] view plain copy
     
    1. Picasso.with(StaggeredGridViewDemo.this).load(mImages.get(arg0).getPic()).resize(250, 250).into(new com.squareup.picasso.Target() {  
    2.   
    3.                 @Override  
    4.                 public void onPrepareLoad(Drawable arg0) {  
    5.   
    6.                 }  
    7.   
    8.                 @Override  
    9.                 public void onBitmapLoaded(Bitmap arg0, LoadedFrom arg1) {  
    10.                     Log.i("llj", "arg0.getWidth()+arg0.getHeight()" + arg0.getWidth() + ";" + arg0.getHeight());  
    11.                 }  
    12.   
    13.                 @Override  
    14.                 public void onBitmapFailed(Drawable arg0) {  
    15.   
    16.                 }  
    17.             });  

    说明两者的按比例缩放的方法不一样!

  • 相关阅读:
    SpringMVC案例3----spring3.0项目拦截器、ajax、文件上传应用
    TCP/IP、UDP、 Http、Socket的差别
    HttpClient 图讲解明
    数据库设计--数据的垂直拆分
    未经处理的异常在 System.Data.dll 中发生。其它信息:在应使用条件的上下文(在 &#39;***&#39; 附近)中指定了非布尔类型的表达式。
    VMware 下扩展linux硬盘空间
    cocos2d_android 第一个游戏
    解决安卓程序安装没图标的问题
    Qt编译错误GL/gl.h: No such file or directory
    【编程题目】二元树的深度
  • 原文地址:https://www.cnblogs.com/AceIsSunshineRain/p/5196986.html
Copyright © 2011-2022 走看看