Android Studio 第五十四期 - 超级巨图Glide3.7和Glide4.1.1优化加载方案

Android Studio 第五十四期 - 超级巨图Glide3.7和Glide4.1.1优化加载方案_第1张图片  Android Studio 第五十四期 - 超级巨图Glide3.7和Glide4.1.1优化加载方案_第2张图片


wKiom1nA9iSRwF1BADe7ZVL2w4Q127.jpg

    相信大家看到上面的巨图会很懵逼~最近产品经理朝令夕改,有点烦,要不是还有外包项目在做,就不想干了,所以忍了,先做完十一后再说,毕竟找工作还是有点折腾,需要更高的薪水和技术的沉淀。好吧,啰嗦了一把,下面开始正题,最近一直在研究glide3.7和glide4.1.1,两者的方法确实改变不少,网上给的方案大多都是浅显的使用,目前没有找到git上详细使用的开源的统一的代码,我也是查了一周的代码,最后还是搞出来了一些东西,希望可以帮到你。

    首先是glide3.7的使用,比较单一,如果你要结合okhttp一起使用,全部的代码引用如下代码:

//glide37
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
compile 'com.squareup.okhttp3:okhttp:3.4.2'

    使用的话如下代码:

GlideUtil.display(context, viewHolder.iv_imgurl, ratings.getSku_image(), GlideOptionsFactory.get(GlideOptionsFactory.Type.RADIUS));


Glide.with(context).load(ratings.getSku_image()).skipMemoryCache(true).diskCacheStrategy(DiskCacheStrategy.NONE).into(viewHolder.iv_imgurl);


GlideOptions glideOptions = new GlideOptions(R.drawable.ic_def_loading, R.drawable.ic_def_loading, 300);

GlideUtil.display(context, viewHolder.iv1, ratings.getImg_url(), glideOptions);

    这里说一下,我封装了一下3.7的方法,可以自定义圆角,但是清理缓存的操作建议还是用原生的方法。

    可以参考之前写的demo:

    https://github.com/geeklx/MyApplication/tree/master/P009_Glide图片缓存

    3.7还是很好用的,目前项目中大家应该都在用这个版本,不过4.0出来以后大幅度修改了API让很多人望而却步,我也是因为怕被技术无形的淘汰,逼了自己一把,把4.1.1的版本API都看了一遍,整体感觉4.1.1的版本还是要好一些,如果说3.7只是基础的用法,那么4.1.1就是晋升之路,学会后你会发现,有很多市面上你见过的通用的业务都不需要你去自己写页面,glide4.1.1会给你提供很好的自定义解决方案。

    下面开始正题:当你遇到清明上河图或者微博的大图预览,你会怎么做?是不是按部就班的画页面,传值,折腾几夜,然后也做出来了,挺辛苦和费劲的。现在glide4.1.1就提供了很好的便利,再说4.1.1之前先看看3.7怎么封装它,让它也实现功能。

    Glide3.7基础用法以及大图预览放大效果:

    LargeImageViewTarget:

package com.example.shining.p042_largeimage.glide37;

import android.graphics.drawable.Drawable;
import android.view.View;

import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.ViewTarget;
import com.shizhefei.view.largeimage.ILargeImageView;
import com.shizhefei.view.largeimage.factory.FileBitmapDecoderFactory;

import java.io.File;

/**
 * A base {@link com.bumptech.glide.request.target.Target} for displaying resources in
 * {@link android.widget.ImageView}s.
 *
 * @param  The type of resource that this target will display in the wrapped {@link android.widget.ImageView}.
 */
public class LargeImageViewTarget extends ViewTarget{
    private ILargeImageView largeImageView;
    public  LargeImageViewTarget(V view) {
        super(view);
        this.largeImageView = view;
    }

    /**
     * Sets the given {@link android.graphics.drawable.Drawable} on the view using
     * {@link android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
     *
     * @param placeholder {@inheritDoc}
     */
    @Override
    public void onLoadStarted(Drawable placeholder) {
        largeImageView.setImageDrawable(placeholder);
    }

    /**
     * Sets the given {@link android.graphics.drawable.Drawable} on the view using
     * {@link android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
     *
     * @param errorDrawable {@inheritDoc}
     */
    @Override
    public void onLoadFailed(Exception e, Drawable errorDrawable) {
        largeImageView.setImageDrawable(errorDrawable);
    }

    @Override
    public void onResourceReady(File resource, GlideAnimation glideAnimation) {
        largeImageView.setImage(new FileBitmapDecoderFactory(resource));
    }

    /**
     * Sets the given {@link android.graphics.drawable.Drawable} on the view using
     * {@link android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
     *
     * @param placeholder {@inheritDoc}
     */
    @Override
    public void onLoadCleared(Drawable placeholder) {
        largeImageView.setImageDrawable(placeholder);
    }
}

    OkHttpProgressGlideModule:

package com.example.shining.p042_largeimage.glide37;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.GlideModule;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

// TODO add 
// TODO add 
// or not use 'okhttp@aar' in Gradle depdendencies
public class OkHttpProgressGlideModule implements GlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
    }

    @Override
    public void registerComponents(Context context, Glide glide) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.networkInterceptors().add(createInterceptor(new DispatchingProgressListener()));
        glide.register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(builder.build()));
    }

    private static Interceptor createInterceptor(final ResponseProgressListener listener) {
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Response response = chain.proceed(request);
                return response.newBuilder()
                        .body(new OkHttpProgre***esponseBody(request.url(), response.body(), listener))
                        .build();
            }
        };
    }

    public interface UIProgressListener {
        void onProgress(long bytesRead, long expectedLength);

        /**
         * Control how often the listener needs an update. 0% and 100% will always be dispatched.
         *
         * @return in percentage (0.2 = call {@link #onProgress} around every 0.2 percent of progress)
         */
        float getGranualityPercentage();
    }

    public static void forget(String url) {
        DispatchingProgressListener.forget(url);
    }

    public static void expect(String url, UIProgressListener listener) {
        DispatchingProgressListener.expect(url, listener);
    }

    private interface ResponseProgressListener {
        void update(HttpUrl url, long bytesRead, long contentLength);
    }

    private static class DispatchingProgressListener implements ResponseProgressListener {
        private static final Map LISTENERS = new ConcurrentHashMap<>();
        private static final Map PROGRESSES = new ConcurrentHashMap<>();

        private final Handler handler;

        DispatchingProgressListener() {
            this.handler = new Handler(Looper.getMainLooper());
        }

        static void forget(String url) {
            LISTENERS.remove(url);
            PROGRESSES.remove(url);
        }

        static void expect(String url, UIProgressListener listener) {
            LISTENERS.put(url, listener);
        }

        @Override
        public void update(HttpUrl url, final long bytesRead, final long contentLength) {
            //System.out.printf("%s: %d/%d = %.2f%%%n", url, bytesRead, contentLength, (100f * bytesRead) / contentLength);
            String key = url.toString();
            final UIProgressListener listener = LISTENERS.get(key);
            if (listener == null) {
                return;
            }
            //长度是错误的移除监听
            if (contentLength <= bytesRead) {
                forget(key);
            }
            if (needsDispatch(key, bytesRead, contentLength, listener.getGranualityPercentage())) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        listener.onProgress(bytesRead, contentLength);
                    }
                });
            }
        }

        private boolean needsDispatch(String key, long current, long total, float granularity) {
            if (granularity == 0 || current == 0 || total == current) {
                return true;
            }
            float percent = 100f * current / total;
            long currentProgress = (long) (percent / granularity);
            Long lastProgress = PROGRESSES.get(key);
            if (lastProgress == null || currentProgress != lastProgress) {
                PROGRESSES.put(key, currentProgress);
                return true;
            } else {
                return false;
            }
        }
    }

    private static class OkHttpProgre***esponseBody extends ResponseBody {
        private final HttpUrl url;
        private final ResponseBody responseBody;
        private final ResponseProgressListener progressListener;
        private BufferedSource bufferedSource;

        OkHttpProgre***esponseBody(HttpUrl url, ResponseBody responseBody,
                                   ResponseProgressListener progressListener) {
            this.url = url;
            this.responseBody = responseBody;
            this.progressListener = progressListener;
        }

        @Override
        public MediaType contentType() {
            return responseBody.contentType();
        }

        @Override
        public long contentLength() {
            return responseBody.contentLength();
        }

        @Override
        public BufferedSource source() {
            if (bufferedSource == null) {
                bufferedSource = Okio.buffer(source(responseBody.source()));
            }
            return bufferedSource;
        }

        private Source source(Source source) {
            return new ForwardingSource(source) {
                long totalBytesRead = 0L;

                @Override
                public long read(Buffer sink, long byteCount) throws IOException {
                    long bytesRead = super.read(sink, byteCount);
                    long fullLength = responseBody.contentLength();
                    if (bytesRead == -1) { // this source is exhausted
                        totalBytesRead = fullLength;
                    } else {
                        totalBytesRead += bytesRead;
                    }
                    progressListener.update(url, totalBytesRead, fullLength);
                    return bytesRead;
                }
            };
        }
    }
}

    这里需要注意一下,需要延迟配置GlideModule,

    xml:


    onCreate:

final Glide glide = Glide.get(this);
OkHttpProgressGlideModule a = new OkHttpProgressGlideModule();
a.registerComponents(this, glide);

    这里这样写的原因是在你加载图片的时候给加载的进度过程,自定义OkHttpProgressGlideModule,

    ProgressTarget:

package com.example.shining.p042_largeimage.glide37;

import android.graphics.drawable.Drawable;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.Target;

public abstract class ProgressTarget extends WrappingTarget implements OkHttpProgressGlideModule.UIProgressListener {
    private T model;
    private boolean ignoreProgress = true;

    public ProgressTarget(T model, Target target) {
        super(target);
        this.model = model;
    }

    public final T getModel() {
        return model;
    }

    public final void setModel(T model) {
        Glide.clear(this); // indirectly calls cleanup
        this.model = model;
    }

    /**
     * Convert a model into an Url string that is used to match up the OkHttp requests. For explicit
     * {@link com.bumptech.glide.load.model.GlideUrl GlideUrl} loads this needs to return
     * {@link com.bumptech.glide.load.model.GlideUrl#toStringUrl toStringUrl}. For custom models do the same as your
     * {@link com.bumptech.glide.load.model.stream.BaseGlideUrlLoader BaseGlideUrlLoader} does.
     *
     * @param model return the representation of the given model, DO NOT use {@link #getModel()} inside this method.
     * @return a stable Url representation of the model, otherwise the progress reporting won't work
     */
    protected String toUrlString(T model) {
        return String.valueOf(model);
    }

    @Override
    public float getGranualityPercentage() {
        return 1.0f;
    }

    private void start() {
        OkHttpProgressGlideModule.expect(toUrlString(model), this);
        ignoreProgress = false;
    }

    private void cleanup() {
        ignoreProgress = true;
        T model = this.model; // save in case it gets modified
        OkHttpProgressGlideModule.forget(toUrlString(model));
        this.model = null;
    }

    @Override
    public void onLoadStarted(Drawable placeholder) {
        super.onLoadStarted(placeholder);
        start();
    }

    @Override
    public void onResourceReady(Z resource, GlideAnimation animation) {
        cleanup();
        super.onResourceReady(resource, animation);
    }

    @Override
    public void onLoadFailed(Exception e, Drawable errorDrawable) {
        cleanup();
        super.onLoadFailed(e, errorDrawable);
    }

    @Override
    public void onLoadCleared(Drawable placeholder) {
        cleanup();
        super.onLoadCleared(placeholder);
    }
}

    WrappingTarget:

package com.example.shining.p042_largeimage.glide37;

import android.graphics.drawable.Drawable;

import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SizeReadyCallback;
import com.bumptech.glide.request.target.Target;

public class WrappingTarget implements Target {
    protected final Target target;

    public WrappingTarget(Target target) {
        this.target = target;
    }

    @Override
    public void getSize(SizeReadyCallback cb) {
        if (target != null)
            target.getSize(cb);
    }

    @Override
    public void onLoadStarted(Drawable placeholder) {
        if (target != null)
            target.onLoadStarted(placeholder);
    }

    @Override
    public void onLoadFailed(Exception e, Drawable errorDrawable) {
        if (target != null)
            target.onLoadFailed(e, errorDrawable);
    }

    @Override
    public void onResourceReady(Z resource, GlideAnimation glideAnimation) {
        if (target != null)
            target.onResourceReady(resource, glideAnimation);
    }

    @Override
    public void onLoadCleared(Drawable placeholder) {
        if (target != null) target.onLoadCleared(placeholder);
    }

    private Request request;

    @Override
    public Request getRequest() {
        return request;
    }

    @Override
    public void setRequest(Request request) {
        this.request = request;
        if (target != null)
            target.setRequest(request);
    }

    @Override
    public void onStart() {
        if (target != null)
            target.onStart();
    }

    @Override
    public void onStop() {
        if (target != null)
            target.onStop();
    }

    @Override
    public void onDestroy() {
        if (target != null) target.onDestroy();
    }
}

    buildgradle:

//largeimage
compile 'com.shizhefei:LargeImageView:1.0.9'
compile 'com.github.HotBitmapGG:RingProgressBar:V1.2.2'

    加载网络图片MainActivityLargeImageGlide:

package com.example.shining.p042_largeimage.activity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.SizeReadyCallback;
import com.bumptech.glide.request.target.Target;
import com.example.shining.p042_largeimage.R;
import com.example.shining.p042_largeimage.glide37.OkHttpProgressGlideModule;
import com.example.shining.p042_largeimage.glide37.ProgressTarget;
import com.shizhefei.view.largeimage.LargeImageView;
import com.shizhefei.view.largeimage.factory.FileBitmapDecoderFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import io.netopen.hotbitmapgg.library.view.RingProgressBar;

public class MainActivityLargeImageGlide extends AppCompatActivity {

    private LargeImageView largeImageView;
    private RingProgressBar ringProgressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_large_image_view);

        largeImageView = (LargeImageView) findViewById(R.id.networkDemo_photoView);
        ringProgressBar = (RingProgressBar) findViewById(R.id.networkDemo_ringProgressBar);
//        String url = "http://short.im.rockhippo.cn/uploads/msg/201703/20170309/1485/1489068660846.jpg";
//        URL fileUrl = null;
//        File file = null;
//        try {
//            fileUrl = new URL(url);
//            file = new File(fileUrl.toURI());
//        } catch (MalformedURLException | URISyntaxException e) {
//            e.printStackTrace();
//        }
//
//        assert file != null;
//        largeImageView.setImage(new FileBitmapDecoderFactory(file));

//        String url = "https://s2.51cto.com/wyfs02/M02/06/F4/wKiom1nA9iSRwF1BADe7ZVL2w4Q127.jpg";
//        String url = "https://s2.51cto.com/wyfs02/M00/06/F4/wKiom1nA-Aiy9qMkAAR3_qzZ1is031.jpg";
        String url = "https://s3.51cto.com/wyfs02/M00/A5/A5/wKioL1nA-WrQ8NSkAADpAlDnsrM054.jpg";
        final Glide glide = Glide.get(this);
        OkHttpProgressGlideModule a = new OkHttpProgressGlideModule();
        a.registerComponents(this, glide);
        new Thread() {
            @Override
            public void run() {
                super.run();
                Glide.get(getApplicationContext()).clearDiskCache();
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
//                        Toast.makeText(getApplicationContext(), "清除缓存成功", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }.start();
        Glide.with(this).load(url).downloadOnly(new ProgressTarget(url, null) {
            @Override
            public void onLoadStarted(Drawable placeholder) {
                super.onLoadStarted(placeholder);
                ringProgressBar.setVisibility(View.VISIBLE);
                ringProgressBar.setProgress(0);
            }

            @Override
            public void onProgress(long bytesRead, long expectedLength) {
                int p = 0;
                if (expectedLength >= 0) {
                    p = (int) (100 * bytesRead / expectedLength);
                }
                ringProgressBar.setProgress(p);
            }

            @Override
            public void onResourceReady(File resource, GlideAnimation animation) {
                super.onResourceReady(resource, animation);
                ringProgressBar.setVisibility(View.GONE);
//                largeImageView.setEnabled(false);
                largeImageView.setImage(new FileBitmapDecoderFactory(resource));
            }

            @Override
            public void getSize(SizeReadyCallback cb) {
                cb.onSizeReady(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
            }
        });

    }

    /**
     * 根据图片的url路径获得Bitmap对象
     *
     * @param url
     * @return
     */
    private Bitmap returnBitmap(String url) {
        URL fileUrl = null;
        Bitmap bitmap = null;
        try {
            fileUrl = new URL(url);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        try {
            HttpURLConnection conn = (HttpURLConnection) fileUrl.openConnection();
            conn.setDoInput(true);
            conn.connect();
            InputStream is = conn.getInputStream();
            bitmap = BitmapFactory.decodeStream(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bitmap;

    }
}

    加载本地assets文件夹大图,这里要说一下,经过测试,手机取drawable里面的巨图会OOM,平板不会,但是assets目录手机和平板都支持,因为drawable取的是路径加载,assets是文件流,所以不会OOM,

    加载drawable目录 MainActivityLargeImageLocal1:

package com.example.shining.p042_largeimage.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.example.shining.p042_largeimage.R;
import com.shizhefei.view.largeimage.LargeImageView;

public class MainActivityLargeImageLocal1 extends AppCompatActivity {

    private LargeImageView localDemo_photoView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_largeimage_local);
        localDemo_photoView = (LargeImageView) findViewById(R.id.localDemo_photoView);

        String fileName = getIntent().getStringExtra("file_name");
        localDemo_photoView.setImage(getResources().getDrawable(R.drawable.qm3));
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                localDemo_photoView.setScale(0.5f);
            }
        });

    }

}

    加载assets目录 MainActivityLargeImageLocal2:

package com.example.shining.p042_largeimage.activity;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.example.shining.p042_largeimage.R;
import com.shizhefei.view.largeimage.BlockImageLoader;
import com.shizhefei.view.largeimage.LargeImageView;
import com.shizhefei.view.largeimage.factory.InputStreamBitmapDecoderFactory;

import java.io.IOException;
import java.io.InputStream;


public class MainActivityLargeImageLocal2 extends AppCompatActivity {

    private LargeImageView largeImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_largeimage_local);
        largeImageView = (LargeImageView) findViewById(R.id.localDemo_photoView);

        try {
            String fileName = getIntent().getStringExtra("file_name");
            //通过文件的方式加载sd卡中的大图
//            localDemo_photoView.setImage(new FileBitmapDecoderFactory(file));
            //通过流的方式加载assets文件夹里面的大图
            InputStream inputStream = getAssets().open("qm.jpg");
            largeImageView.setImage(new InputStreamBitmapDecoderFactory(inputStream));
//            localDemo_photoView.setImage(new InputStreamBitmapDecoderFactory(inputStream), getResources().getDrawable(R.drawable.mvc));
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    largeImageView.setScale(0.5f);
                    largeImageView.setOnImageLoadListener(new BlockImageLoader.OnImageLoadListener() {
                        @Override
                        public void onBlockImageLoadFinished() {

                        }

                        @Override
                        public void onLoadImageSize(int imageWidth, int imageHeight) {
                            String a = imageHeight + "";
                        }

                        @Override
                        public void onLoadFail(Exception e) {

                        }
                    });

//                    largeImageView.setCriticalScaleValueHook(new LargeImageView.CriticalScaleValueHook() {
//                        @Override
//                        public float getMinScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMinScale) {
//                            return 15;
//                        }
//
//                        @Override
//                        public float getMaxScale(LargeImageView largeImageView, int imageWidth, int imageHeight, float suggestMaxScale) {
//                            return 30;
//                        }
//                    });
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

    这里给你提供一下小细节,大部分人在后台返回色值或者UI设计0%透明度的时候烦恼,给大家记录一下透明的计算方法:

     #00ffffff
     00这两位的计算:255*50%(透明度UI会告诉你)=结果128转化成16进制就是80这两位你需要的。

    colorUtil:




    #3F51B5
    #303F9F
    #FF4081

    #dfdfdf
    #ffffff
    
    #fffff0
    
    #ffffe0
    
    #ffff00
    
    #fffafa
    
    #fffaf0
    
    #fffacd
    
    #fff8dc
    
    #fff5ee
    
    #fff0f5
    
    #ffefd5
    
    #ffebcd
    
    #ffe4e1
    
    #ffe4c4
    
    #ffe4b5
    
    #ffdead
    
    #ffdab9
    
    #ffd700
    
    #ffc0cb
    
    #ffb6c1
    
    #ffa500
    
    #ffa07a
    
    #ff8c00
    
    #ff7f50
    
    #ff69b4
    
    #ff6347
    
    #ff4500
    
    #ff1493
    
    #ff00ff
    
    #ff00ff
    
    #ff0000
    
    #fdf5e6
    
    #fafad2
    
    #faf0e6
    
    #faebd7
    
    #fa8072
    
    #f8f8ff
    
    #f5fffa
    
    #f5f5f5
    
    #f5f5dc
    
    #f5deb3
    
    #f4a460
    
    #f0ffff
    
    #f0fff0
    
    #f0f8ff
    
    #f0e68c
    
    #f08080
    
    #eee8aa
    
    #ee82ee
    
    #e9967a
    
    #e6e6fa
    
    #e0ffff
    
    #deb887
    
    #dda0dd
    
    #dcdcdc
    
    #dc143c
    
    #db7093
    
    #daa520
    
    #da70d6
    
    #d8bfd8
    
    #d3d3d3
    
    #d3d3d3
    
    #d2b48c
    
    #d2691e
    
    #cd853f
    
    #cd5c5c
    
    #c71585
    
    #c0c0c0
    
    #bdb76b
    
    #bc8f8f
    
    #ba55d3
    
    #b8860b
    
    #b22222
    
    #b0e0e6
    
    #b0c4de
    
    #afeeee
    
    #adff2f
    
    #add8e6
    
    #a9a9a9
    
    #a9a9a9
    
    #a52a2a
    
    #a0522d
    
    #9932cc
    
    #98fb98
    
    #9400d3
    
    #9370db
    
    #90ee90
    
    #8fbc8f
    
    #8b4513
    
    #8b008b
    
    #8b0000
    
    #8a2be2
    
    #87cefa
    
    #87ceeb
    
    #808080
    
    #808080
    
    #808000
    
    #800080
    
    #800000
    
    #7fffd4
    
    #7fff00
    
    #7cfc00
    
    #7b68ee
    
    #778899
    
    #778899
    
    #708090
    
    #708090
    
    #6b8e23
    
    #6a5acd
    
    #696969
    
    #696969
    
    #66cdaa
    
    #6495ed
    
    #5f9ea0
    
    #556b2f
    
    #4b0082
    
    #48d1cc
    
    #483d8b
    
    #4682b4
    
    #4169e1
    
    #40e0d0
    
    #3cb371
    
    #32cd32
    
    #2f4f4f
    
    #2f4f4f
    
    #2e8b57
    
    #228b22
    
    #20b2aa
    
    #1e90ff
    
    #191970
    
    #00ffff
    
    #00ffff
    
    #00ff7f
    
    #00ff00
    
    #00fa9a
    
    #00ced1
    
    #00bfff
    
    #008b8b
    
    #008080
    
    #008000
    
    #006400
    
    #0000ff
    
    #0000cd
    
    #00008b
    
    #000080
    
    #000000
    
    #0000
    
    #8000
    

    #ff4c41
    #C9C7CD
   
    #ff000000
    #D9000000
    #8C000000
    #66000000
    #1A000000
    #C34A42
    #FF9800
    #009734
    #46AE36
    #47B000
    #007AFF
    #1194F6
    #9D1BB2

    #00000000
    #0B000000
    #1A000000
    #33000000
    #4D000000
    #66000000
    #80000000
    #9A000000
    #B3000000
    #CC000000
    #E5000000
    #FF000000

    #00ffffff
    #1Affffff
    #33ffffff
    #4Dffffff
    #66ffffff
    #80ffffff
    #9Affffff
    #B3ffffff
    #CCffffff
    #E5ffffff
    #FFffffff

    #1A000000

    #FFFFFF  
    #fbc02d 
    #FFD700   
    #f57c00 
    #d01716    
    #808080   
    #0a7e07  
    #455ede   
    #000000  

    接着是Glide4.1.1的用法

    首先我把开源的代码总结出来了一个library,大家可以打成aarjar或者直接引用,下面介绍用法我是直接引用,建议大家以后打成aar方便,

    glide411library的build.gradle:

compile 'com.android.support:support-v4:26.0.0-alpha1'
compile 'com.github.bumptech.glide:glide:4.1.1'
compile 'com.github.bumptech.glide:compiler:4.1.1'
compile "com.github.bumptech.glide:okhttp3-integration:4.1.1"

    glide411library这里就不贴代码了,给大家提供地址,大家去使用:

    https://github.com/geeklx/MyApplication/tree/master/glide411library

    自己的项目使用glide411以及支持大图功能 build.gradle:

compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
compile 'com.android.support:percent:26.0.0-alpha1'
compile 'com.android.support:design:26.0.0-alpha1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'

//glide411
compile 'com.github.chrisbanes:PhotoView:2.1.3'
compile project(':glide411library')

//largeimage
compile 'com.github.bumptech.glide:glide:4.1.1'
compile 'com.github.bumptech.glide:compiler:4.1.1'
compile "com.github.bumptech.glide:okhttp3-integration:4.1.1"

compile 'com.shizhefei:LargeImageView:1.0.9'
compile 'com.github.HotBitmapGG:RingProgressBar:V1.2.2'

    首先是glidedemo411的基础使用,应该是网上目前见过的最全的吧,我猜~哈哈哈~反正所有的方法我都总结出来了,漏的话不负责~哈哈~

    SingleImageActivity:(预览图Activity)

package com.example.shining.p041_glide411.glidedemo411.image;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestOptions;
import com.example.shining.glide411library.progress.CircleProgressView;
import com.example.shining.glide411library.progress.OnGlideImageViewListener;
import com.example.shining.glide411library.view.GlideImageLoader;
import com.example.shining.glide411library.view.GlideImageView;
import com.example.shining.p041_glide411.R;

import java.util.Random;

public class SingleImageActivity extends AppCompatActivity {

    GlideImageView glideImageView;
    CircleProgressView progressView;

    CircleProgressView progressView1;
    CircleProgressView progressView2;
    CircleProgressView progressView3;
    View maskView;

    public static final String KEY_IMAGE_URL = "image_url";
    public static final String KEY_IMAGE_URL_THUMBNAIL = "image_url_thumbnail";

    String image_url;
    String image_url_thumbnail;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_glide411_image);

        glideImageView = (GlideImageView) findViewById(R.id.glideImageView);
        progressView1 = (CircleProgressView) findViewById(R.id.progressView1);
        progressView2 = (CircleProgressView) findViewById(R.id.progressView2);
        progressView3 = (CircleProgressView) findViewById(R.id.progressView3);
        maskView = findViewById(R.id.maskView);

        image_url = getIntent().getStringExtra(KEY_IMAGE_URL);
        image_url_thumbnail = getIntent().getStringExtra(KEY_IMAGE_URL_THUMBNAIL);

        initProgressView();
        loadImage();
    }

    private void initProgressView() {
//        MainActivityGlide.isLoadAgain = new Random().nextInt(3) == 1;
        int randomNum = new Random().nextInt(3);
        switch (randomNum) {
            case 1:
                progressView = progressView2;
                break;
            case 2:
                progressView = progressView3;
                break;
            case 0:
            default:
                progressView = progressView1;
                break;
        }
        progressView1.setVisibility(View.GONE);
        progressView2.setVisibility(View.GONE);
        progressView3.setVisibility(View.GONE);
        progressView.setVisibility(View.VISIBLE);
    }

    private void loadImage() {
        glideImageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ActivityCompat.finishAfterTransition(SingleImageActivity.this);
            }
        });

        RequestOptions requestOptions = glideImageView.requestOptions(R.color.black)
                .centerCrop();
        RequestOptions requestOptionsWithoutCache = glideImageView.requestOptions(R.color.black)
                .centerCrop()
                .skipMemoryCache(true)
                .diskCacheStrategy(DiskCacheStrategy.NONE);

        GlideImageLoader imageLoader = glideImageView.getImageLoader();

        imageLoader.setOnGlideImageViewListener(image_url, new OnGlideImageViewListener() {
            @Override
            public void onProgress(int percent, boolean isDone, GlideException exception) {
                if (exception != null && !TextUtils.isEmpty(exception.getMessage())) {
                    Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
                }
                progressView.setProgress(percent);
                Log.d("--->imageLoader", "percent: " + percent + " isDone: " + isDone);
                progressView.setVisibility(isDone ? View.GONE : View.VISIBLE);
                maskView.setVisibility(isDone ? View.GONE : View.VISIBLE);
            }
        });

        imageLoader.requestBuilder(image_url, requestOptionsWithoutCache)
                .thumbnail(Glide.with(SingleImageActivity.this)
                        .load(image_url_thumbnail)
                        .apply(requestOptions))
                .transition(DrawableTransitionOptions.withCrossFade())
                .into(glideImageView);
    }
}

    MainActivityGlide:(411demo Activity)

package com.example.shining.p041_glide411.glidedemo411;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
import com.bumptech.glide.request.RequestOptions;
import com.example.shining.glide411library.progress.CircleProgressView;
import com.example.shining.glide411library.progress.OnGlideImageViewListener;
import com.example.shining.glide411library.progress.OnProgressListener;
import com.example.shining.glide411library.view.GlideImageLoader;
import com.example.shining.glide411library.view.GlideImageView;
import com.example.shining.glide411library.view.ShapeImageView;
import com.example.shining.p041_glide411.R;
import com.example.shining.p041_glide411.glidedemo411.image.SingleImageActivity;

import java.util.Random;

import static com.example.shining.p041_glide411.glidedemo411.image.SingleImageActivity.KEY_IMAGE_URL;
import static com.example.shining.p041_glide411.glidedemo411.image.SingleImageActivity.KEY_IMAGE_URL_THUMBNAIL;


public class MainActivityGlide extends AppCompatActivity {

    private GlideImageView image11;
    private GlideImageView image12;
    private GlideImageView image13;
    private GlideImageView image14;
    private String url1 = "https://s3.51cto.com/wyfs02/M01/89/BA/wKioL1ga-u7QnnVnAAAfrCiGnBQ946_middle.jpg";

    private GlideImageView image21;
    private GlideImageView image22;
    private GlideImageView image23;
    private GlideImageView image24;

    private GlideImageView image31;
    private GlideImageView image32;
    private GlideImageView image33;
    private GlideImageView image34;
    private String gif1 = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1505394298896&di=98e0e804231a282ef80360e94fa7dca6&imgtype=0&src=http%3A%2F%2Fimg.qqai.net%2Fuploads%2Fi_3_2854471891x1596414192_21.jpg";

    private GlideImageView image41;
    private CircleProgressView progressView1;
    private String image41BigUrl = "https://raw.githubusercontent.com/geeklx/MyApplication/master/p040_glide4.0/screenshot/1232.png";
    private String image41SmallUrl = "https://raw.githubusercontent.com/geeklx/MyApplication/master/p040_glide4.0/screenshot/1231.png";

    private GlideImageView image42;
    private CircleProgressView progressView2;
    private String image42BigUrl = "https://raw.githubusercontent.com/geeklx/MyApplication/master/p040_glide4.0/screenshot/1234.png";
    private String image42SmallUrl = "https://raw.githubusercontent.com/geeklx/MyApplication/master/p040_glide4.0/screenshot/1233.png";

    public static boolean isLoadAgain = false; // Just for fun when loading images!


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_glide411);

        //Glide
        findview();

        isLoadAgain = new Random().nextInt(3) == 1;

        line1();
        line2();
        line3();
        line41();
        line42();
    }

    private void findview() {
        image11 = (GlideImageView) findViewById(R.id.image11);
        image12 = (GlideImageView) findViewById(R.id.image12);
        image13 = (GlideImageView) findViewById(R.id.image13);
        image14 = (GlideImageView) findViewById(R.id.image14);

        image21 = (GlideImageView) findViewById(R.id.image21);
        image22 = (GlideImageView) findViewById(R.id.image22);
        image23 = (GlideImageView) findViewById(R.id.image23);
        image24 = (GlideImageView) findViewById(R.id.image24);

        image31 = (GlideImageView) findViewById(R.id.image31);
        image32 = (GlideImageView) findViewById(R.id.image32);
        image33 = (GlideImageView) findViewById(R.id.image33);
        image34 = (GlideImageView) findViewById(R.id.image34);

        image41 = (GlideImageView) findViewById(R.id.image41);
        progressView1 = (CircleProgressView) findViewById(R.id.progressView1);
        image42 = (GlideImageView) findViewById(R.id.image42);
        progressView2 = (CircleProgressView) findViewById(R.id.progressView2);
    }

    private void line41() {
        image41.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivityGlide.this, SingleImageActivity.class);
                intent.putExtra(KEY_IMAGE_URL, image41BigUrl);
                intent.putExtra(KEY_IMAGE_URL_THUMBNAIL, image41SmallUrl);
                ActivityOptionsCompat compat = ActivityOptionsCompat
                        .makeSceneTransitionAnimation(MainActivityGlide.this, image41, getString(R.string.transitional_image));
                ActivityCompat.startActivity(MainActivityGlide.this, intent, compat.toBundle());
            }
        });

        RequestOptions requestOptions = image41.requestOptions(R.color.placeholder_color).centerCrop();
        if (isLoadAgain) {
            requestOptions.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true);
        }

        // 第一种方式加载
        image41.load(image41SmallUrl, requestOptions).listener(new OnGlideImageViewListener() {
            @Override
            public void onProgress(int percent, boolean isDone, GlideException exception) {
                if (exception != null && !TextUtils.isEmpty(exception.getMessage())) {
                    Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
                }
                progressView1.setProgress(percent);
                progressView1.setVisibility(isDone ? View.GONE : View.VISIBLE);
            }
        });
    }

    private void line42() {
        image42.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivityGlide.this, SingleImageActivity.class);
                intent.putExtra(KEY_IMAGE_URL, image42BigUrl);
                intent.putExtra(KEY_IMAGE_URL_THUMBNAIL, image42BigUrl);
                ActivityOptionsCompat compat = ActivityOptionsCompat
                        .makeSceneTransitionAnimation(MainActivityGlide.this, image42, getString(R.string.transitional_image));
                ActivityCompat.startActivity(MainActivityGlide.this, intent, compat.toBundle());
            }
        });

        RequestOptions requestOptions = image42.requestOptions(R.color.placeholder_color).centerCrop();
        if (isLoadAgain) {
            requestOptions.diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true);
        }

        // 第二种方式加载:可以解锁更多功能
        GlideImageLoader imageLoader = image42.getImageLoader();
        imageLoader.setOnGlideImageViewListener(image42SmallUrl, new OnGlideImageViewListener() {
            @Override
            public void onProgress(int percent, boolean isDone, GlideException exception) {
                if (exception != null && !TextUtils.isEmpty(exception.getMessage())) {
                    Toast.makeText(getApplicationContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
                }
                progressView2.setProgress(percent);
                progressView2.setVisibility(isDone ? View.GONE : View.VISIBLE);
            }
        });
        imageLoader.requestBuilder(image42SmallUrl, requestOptions)
                .transition(DrawableTransitionOptions.withCrossFade())
                .into(image42);
    }

    private void line3() {
        image31.loadLocalImage(R.drawable.gif_robot_walk, R.drawable.ic_def_loading);

        image32.loadCircleImage(gif1, R.mipmap.ic_launcher).listener(new OnGlideImageViewListener() {
            @Override
            public void onProgress(int percent, boolean isDone, GlideException exception) {
                Log.d("--->image32", "percent: " + percent + " isDone: " + isDone);
            }
        });

        image33.loadImage(gif1, R.drawable.ic_def_loading);
        image34.loadImage(gif1, R.drawable.ic_def_loading);
    }

    private void line2() {
        image21.loadImage(url1, R.drawable.ic_def_loading);
        image22.loadImage("", R.drawable.ic_def_loading);
        image23.loadImage(url1, R.color.placeholder_color);
        image24.loadImage(url1, R.color.placeholder_color);
    }

    private void line1() {
        image11.loadImage(url1, R.color.black).listener(new OnProgressListener() {
            @Override
            public void onProgress(String imageUrl, long bytesRead, long totalBytes, boolean isDone, GlideException exception) {
                Log.d("--->image11", "bytesRead: " + bytesRead + " totalBytes: " + totalBytes + " isDone: " + isDone);
            }
        });
        image12.setShapeType(ShapeImageView.ShapeType.CIRCLE);
        image12.setBorderWidth(3);
        image12.setBorderColor(R.color.transparent20);
        image12.loadCircleImage(url1, R.color.black);
        image12.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(MainActivityGlide.this, "image12", Toast.LENGTH_SHORT).show();
            }
        });

        image13.setShapeType(ShapeImageView.ShapeType.RECTANGLE);
        image13.setRadius(15);
        image13.setBorderWidth(3);
        image13.setBorderColor(R.color.blue);
        image13.setPressedAlpha(0.3f);
        image13.setPressedColor(R.color.blue);
        image13.loadImage(url1, R.color.placeholder_color);

        image14.setShapeType(ShapeImageView.ShapeType.CIRCLE);
        image14.setBorderWidth(3);
        image14.setBorderColor(R.color.blue);
        image14.setPressedAlpha(0.2f);
        image14.setPressedColor(R.color.black);
        image14.loadImage(url1, R.color.placeholder_color);

    }


}

    接下来是largeimage:(用法跟glide3.7一样,我做了兼容,把兼容的代码给大家共享出来,用法看上面的glide3.7)。

    LargeImageViewTarget:

package com.example.shining.p041_glide411.largeimage.glide411;

import android.graphics.drawable.Drawable;
import android.view.View;

import com.bumptech.glide.request.transition.Transition;
import com.bumptech.glide.request.target.ViewTarget;
import com.shizhefei.view.largeimage.ILargeImageView;
import com.shizhefei.view.largeimage.factory.FileBitmapDecoderFactory;

import java.io.File;

/**
 * A base {@link com.bumptech.glide.request.target.Target} for displaying resources in
 * {@link android.widget.ImageView}s.
 *
 * @param  The type of resource that this target will display in the wrapped {@link android.widget.ImageView}.
 */
public class LargeImageViewTarget extends ViewTarget{
    private ILargeImageView largeImageView;
    public  LargeImageViewTarget(V view) {
        super(view);
        this.largeImageView = view;
    }

    /**
     * Sets the given {@link Drawable} on the view using
     * {@link android.widget.ImageView#setImageDrawable(Drawable)}.
     *
     * @param placeholder {@inheritDoc}
     */
    @Override
    public void onLoadStarted(Drawable placeholder) {
        largeImageView.setImageDrawable(placeholder);
    }

    /**
     * Sets the given {@link Drawable} on the view using
     * {@link android.widget.ImageView#setImageDrawable(Drawable)}.
     *
     * @param errorDrawable {@inheritDoc}
     */
    @Override
    public void onLoadFailed(Drawable errorDrawable) {
        largeImageView.setImageDrawable(errorDrawable);
    }

    @Override
    public void onResourceReady(File resource, Transition glideAnimation) {
        largeImageView.setImage(new FileBitmapDecoderFactory(resource));
    }

    /**
     * Sets the given {@link Drawable} on the view using
     * {@link android.widget.ImageView#setImageDrawable(Drawable)}.
     *
     * @param placeholder {@inheritDoc}
     */
    @Override
    public void onLoadCleared(Drawable placeholder) {
        largeImageView.setImageDrawable(placeholder);
    }
}

    OkHttpProgressGlideModule:

package com.example.shining.p041_glide411.largeimage.glide411;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import com.bumptech.glide.Glide;
import com.bumptech.glide.GlideBuilder;
import com.bumptech.glide.Registry;
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.module.AppGlideModule;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

// TODO add 
// TODO add 
// or not use 'okhttp@aar' in Gradle depdendencies
public class OkHttpProgressGlideModule extends AppGlideModule {
    @Override
    public void applyOptions(Context context, GlideBuilder builder) {
    }

    @Override
    public void registerComponents(Context context, Glide glide, Registry registry) {
        super.registerComponents(context, glide, registry);
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.networkInterceptors().add(createInterceptor(new DispatchingProgressListener()));

        glide.getRegistry().append(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(builder.build()));
//        glide.register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(builder.build()));
    }

    private static Interceptor createInterceptor(final ResponseProgressListener listener) {
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                Response response = chain.proceed(request);
                return response.newBuilder()
                        .body(new OkHttpProgre***esponseBody(request.url(), response.body(), listener))
                        .build();
            }
        };
    }


    public interface UIProgressListener {
        void onProgress(long bytesRead, long expectedLength);

        /**
         * Control how often the listener needs an update. 0% and 100% will always be dispatched.
         *
         * @return in percentage (0.2 = call {@link #onProgress} around every 0.2 percent of progress)
         */
        float getGranualityPercentage();
    }

    public static void forget(String url) {
        DispatchingProgressListener.forget(url);
    }

    public static void expect(String url, UIProgressListener listener) {
        DispatchingProgressListener.expect(url, listener);
    }

    private interface ResponseProgressListener {
        void update(HttpUrl url, long bytesRead, long contentLength);
    }

    private static class DispatchingProgressListener implements ResponseProgressListener {
        private static final Map LISTENERS = new ConcurrentHashMap<>();
        private static final Map PROGRESSES = new ConcurrentHashMap<>();

        private final Handler handler;

        DispatchingProgressListener() {
            this.handler = new Handler(Looper.getMainLooper());
        }

        static void forget(String url) {
            LISTENERS.remove(url);
            PROGRESSES.remove(url);
        }

        static void expect(String url, UIProgressListener listener) {
            LISTENERS.put(url, listener);
        }

        @Override
        public void update(HttpUrl url, final long bytesRead, final long contentLength) {
            //System.out.printf("%s: %d/%d = %.2f%%%n", url, bytesRead, contentLength, (100f * bytesRead) / contentLength);
            String key = url.toString();
            final UIProgressListener listener = LISTENERS.get(key);
            if (listener == null) {
                return;
            }
            //长度是错误的移除监听
            if (contentLength <= bytesRead) {
                forget(key);
            }
            if (needsDispatch(key, bytesRead, contentLength, listener.getGranualityPercentage())) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        listener.onProgress(bytesRead, contentLength);
                    }
                });
            }
        }

        private boolean needsDispatch(String key, long current, long total, float granularity) {
            if (granularity == 0 || current == 0 || total == current) {
                return true;
            }
            float percent = 100f * current / total;
            long currentProgress = (long) (percent / granularity);
            Long lastProgress = PROGRESSES.get(key);
            if (lastProgress == null || currentProgress != lastProgress) {
                PROGRESSES.put(key, currentProgress);
                return true;
            } else {
                return false;
            }
        }
    }

    private static class OkHttpProgre***esponseBody extends ResponseBody {
        private final HttpUrl url;
        private final ResponseBody responseBody;
        private final ResponseProgressListener progressListener;
        private BufferedSource bufferedSource;

        OkHttpProgre***esponseBody(HttpUrl url, ResponseBody responseBody,
                                   ResponseProgressListener progressListener) {
            this.url = url;
            this.responseBody = responseBody;
            this.progressListener = progressListener;
        }

        @Override
        public MediaType contentType() {
            return responseBody.contentType();
        }

        @Override
        public long contentLength() {
            return responseBody.contentLength();
        }

        @Override
        public BufferedSource source() {
            if (bufferedSource == null) {
                bufferedSource = Okio.buffer(source(responseBody.source()));
            }
            return bufferedSource;
        }

        private Source source(Source source) {
            return new ForwardingSource(source) {
                long totalBytesRead = 0L;

                @Override
                public long read(Buffer sink, long byteCount) throws IOException {
                    long bytesRead = super.read(sink, byteCount);
                    long fullLength = responseBody.contentLength();
                    if (bytesRead == -1) { // this source is exhausted
                        totalBytesRead = fullLength;
                    } else {
                        totalBytesRead += bytesRead;
                    }
                    progressListener.update(url, totalBytesRead, fullLength);
                    return bytesRead;
                }
            };
        }
    }
}

    ProgressTarget:

package com.example.shining.p041_glide411.largeimage.glide411;

import android.graphics.drawable.Drawable;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.example.shining.p041_glide411.application.DemoApplication;

public abstract class ProgressTarget extends WrappingTarget implements OkHttpProgressGlideModule.UIProgressListener {
    private T model;
    private boolean ignoreProgress = true;

    public ProgressTarget(T model, Target target) {
        super(target);
        this.model = model;
    }

    public final T getModel() {
        return model;
    }

    public final void setModel(T model) {
//        Glide.clear(this); // indirectly calls cleanup
        Glide.with(DemoApplication.mContext).clear(this);
        this.model = model;
    }

    /**
     * Convert a model into an Url string that is used to match up the OkHttp requests. For explicit
     * {@link com.bumptech.glide.load.model.GlideUrl GlideUrl} loads this needs to return
     * {@link com.bumptech.glide.load.model.GlideUrl#toStringUrl toStringUrl}. For custom models do the same as your
     * {@link com.bumptech.glide.load.model.stream.BaseGlideUrlLoader BaseGlideUrlLoader} does.
     *
     * @param model return the representation of the given model, DO NOT use {@link #getModel()} inside this method.
     * @return a stable Url representation of the model, otherwise the progress reporting won't work
     */
    protected String toUrlString(T model) {
        return String.valueOf(model);
    }

    @Override
    public float getGranualityPercentage() {
        return 1.0f;
    }

    private void start() {
        OkHttpProgressGlideModule.expect(toUrlString(model), this);
        ignoreProgress = false;
    }

    private void cleanup() {
        ignoreProgress = true;
        T model = this.model; // save in case it gets modified
        OkHttpProgressGlideModule.forget(toUrlString(model));
        this.model = null;
    }

    @Override
    public void onLoadStarted(Drawable placeholder) {
        super.onLoadStarted(placeholder);
        start();
    }

    @Override
    public void onResourceReady(Z resource, Transition animation) {
        cleanup();
        super.onResourceReady(resource, animation);
    }

    @Override
    public void onLoadFailed(Drawable errorDrawable) {
        cleanup();
        super.onLoadFailed(errorDrawable);
    }

    @Override
    public void onLoadCleared(Drawable placeholder) {
        cleanup();
        super.onLoadCleared(placeholder);
    }
}

    WrappingTarget:

package com.example.shining.p041_glide411.largeimage.glide411;

import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;

import com.bumptech.glide.request.Request;
import com.bumptech.glide.request.target.SizeReadyCallback;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;

public class WrappingTarget implements Target {
    protected final Target target;

    public WrappingTarget(Target target) {
        this.target = target;
    }

    @Override
    public void getSize(SizeReadyCallback cb) {
        if (target != null)
            target.getSize(cb);
    }

    @Override
    public void removeCallback(SizeReadyCallback cb) {

    }

    @Override
    public void onLoadStarted(Drawable placeholder) {
        if (target != null)
            target.onLoadStarted(placeholder);
    }

    @Override
    public void onLoadFailed(@Nullable Drawable errorDrawable) {
        if (target != null)
            target.onLoadFailed(errorDrawable);
    }

    @Override
    public void onResourceReady(Z resource, Transition glideAnimation) {
        if (target != null)
            target.onResourceReady(resource, glideAnimation);
    }

    @Override
    public void onLoadCleared(Drawable placeholder) {
        if (target != null) target.onLoadCleared(placeholder);
    }

    private Request request;

    @Override
    public Request getRequest() {
        return request;
    }

    @Override
    public void setRequest(Request request) {
        this.request = request;
        if (target != null)
            target.setRequest(request);
    }

    @Override
    public void onStart() {
        if (target != null)
            target.onStart();
    }

    @Override
    public void onStop() {
        if (target != null)
            target.onStop();
    }

    @Override
    public void onDestroy() {
        if (target != null) target.onDestroy();
    }
}

    权限别忘了:






    效果如下图:

    图1:

    Android Studio 第五十四期 - 超级巨图Glide3.7和Glide4.1.1优化加载方案_第3张图片

    图2:    

    Android Studio 第五十四期 - 超级巨图Glide3.7和Glide4.1.1优化加载方案_第4张图片

    图3:

    

    图4:

      

    今天介绍了很多东西,希望能帮到你~谢谢~

    附:

    glide3.7的地址:https://github.com/geeklx/MyApplication/tree/master/p042_largeimage

    glide4.1.1的地址:https://github.com/geeklx/MyApplication/tree/master/p041_glide411

    glide3.7图片加载地址:

    https://github.com/geeklx/MyApplication/tree/master/P009_Glide图片缓存

    glide4.1.1图片加载地址:

    https://github.com/geeklx/MyApplication/tree/master/p009_glide图片缓存411

    Android Studio 第五十四期 - 超级巨图Glide3.7和Glide4.1.1优化加载方案_第5张图片


你可能感兴趣的:(Android Studio 第五十四期 - 超级巨图Glide3.7和Glide4.1.1优化加载方案)