• Diycode开源项目 Glide图片加载分析


    1.使用Glide前的准备

    1.1.首先要build.gradle中添加

       

      github原地址点击我。

      参考博客:Glide-开始!

      参考博客:android图片加载库Glide的使用介绍。

      参考博客:Google推荐的图片加载库Glide介绍。

      所有有关Glide的源头都是来自于github,首先亮一手,可以自己去看看。

    1.2.有必要添加混淆

      为了APP的安全,现在一般都要求添加混淆

      

      在github上复制粘贴即可。

    1.3.最简单的用法==>对于一个简单的view

      

      了解这么多就行了。


    2.用Module自定义Glide

    2.1.Glide Module存在的意义

      Glide Module是一个抽象方法,全局改变Glide行为的一个方法。如果你需要GlideBuilder,它要在你要做的地方

      创建Glide实例。这是要做的一种方法。为了定制Glide,你需要去实现一个GlideModule接口的公共类。

      

      

    2.2.需要在AndroidManifest.xml中声明这个Glide module。

      

    2.3.然后就可以对这个Module为所欲为了。

      有这些方法可以用的。

      

      实际的项目中是这样用的。

      

      设置了内存缓存==10M

      设置了磁盘缓存==250M

    2.4.还可以增加Glide的图片质量,用的也比较多

      


    3.自定义Drawable实现Drawable.Callback

    3.1.首先了解一下Drawable

        关于自定义Drawable,可以参考一下这篇文章。

      

      

      

    3.2.然后了解一下Drawble.Callback回调接口

     

    3.3.本项目的源代码

    /*
     * Copyright 2017 GcsSloop
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *    http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     * Last modified 2017-03-11 22:24:02
     *
     * GitHub:  https://github.com/GcsSloop
     * Website: http://www.gcssloop.com
     * Weibo:   http://weibo.com/GcsSloop
     */
    
    package com.gcssloop.diycode.base.glide;
    
    import android.graphics.Canvas;
    import android.graphics.ColorFilter;
    import android.graphics.drawable.Drawable;
    
    import com.bumptech.glide.load.resource.drawable.GlideDrawable;
    
    /**
     * 为 {@link GlideImageGetter} 服务
     */
    public class UrlDrawable extends Drawable implements Drawable.Callback {
    
        private GlideDrawable mDrawable;
    
        @Override
        public void draw(Canvas canvas) {
            if (mDrawable != null) {
                mDrawable.draw(canvas);
            }
        }
    
        @Override
        public void setAlpha(int alpha) {
            if (mDrawable != null) {
                mDrawable.setAlpha(alpha);
            }
        }
    
        @Override
        public void setColorFilter(ColorFilter cf) {
            if (mDrawable != null) {
                mDrawable.setColorFilter(cf);
            }
        }
    
        @Override
        public int getOpacity() {
            if (mDrawable != null) {
                return mDrawable.getOpacity();
            }
            return 0;
        }
    
        public void setDrawable(GlideDrawable drawable) {
            if (this.mDrawable != null) {
                this.mDrawable.setCallback(null);
            }
            drawable.setCallback(this);
            this.mDrawable = drawable;
        }
    
        @Override
        public void invalidateDrawable(Drawable who) {
            if (getCallback() != null) {
                getCallback().invalidateDrawable(who);
            }
        }
    
        @Override
        public void scheduleDrawable(Drawable who, Runnable what, long when) {
            if (getCallback() != null) {
                getCallback().scheduleDrawable(who, what, when);
            }
        }
    
        @Override
        public void unscheduleDrawable(Drawable who, Runnable what) {
            if (getCallback() != null) {
                getCallback().unscheduleDrawable(who, what);
            }
        }
    }
    View Code

    3.4.本项目实现Drawable中4个必须实现的函数

      

      其实这里的主角已经悄悄替换成了Glide中的一个GlideDrawble方法了

      这个UrlDrawable就是起一个替换作用,就是自定义一个Drawable可以完美实现GlideDrawable中的所有方法。

    3.5.最关键的setDrawable函数

      

      仅仅这个函数被外部调用了,所以这里既设置了Callback回调,也将外部传进来的GlideDrawable完美附上了值。

    3.6.然后是看一下Drawable.Callback

      这里没有做什么改变,只是因为GlideDrawable要实现这些回调,只能被动去实现3个复写的方法。

      


    4.用Glide加载网络图片,并在textView中显示

    4.1.要实现的功能预览。

      

      如上图,评论中有一张截图+下方的文字。

      整个评论其实是一个TextView。

      问题是如何实现这个功能呢?

    4.2.回顾之前的准备

      我自定义了一个GlideModule,并在清单文件中配置好,有这个东西就行了。  

      然后我自定义了一个UrlDrawable,都是为GlideImageGetter做准备的。

      

      这个是那个评论实现图文混排的关键代码。

      所以我还要定义GlideImageGetter,将content注入这种特殊功能。

    4.3.然后就来关注一下如何实现GlideImageGetter的吧。

    /*
     * Copyright 2017 GcsSloop
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *    http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     * Last modified 2017-03-31 14:20:42
     *
     * GitHub:  https://github.com/GcsSloop
     * Website: http://www.gcssloop.com
     * Weibo:   http://weibo.com/GcsSloop
     */
    
    package com.gcssloop.diycode.base.glide;
    
    import android.content.Context;
    import android.graphics.Rect;
    import android.graphics.drawable.Drawable;
    import android.text.Html;
    import android.view.View;
    import android.widget.TextView;
    
    import com.bumptech.glide.Glide;
    import com.bumptech.glide.load.engine.DiskCacheStrategy;
    import com.bumptech.glide.load.resource.drawable.GlideDrawable;
    import com.bumptech.glide.request.Request;
    import com.bumptech.glide.request.animation.GlideAnimation;
    import com.bumptech.glide.request.target.ViewTarget;
    import com.gcssloop.diycode.R;
    import com.gcssloop.diycode_sdk.log.Logger;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * 用 Glide 加载图片,并在 TextView 中显示
     */
    public final class GlideImageGetter implements Html.ImageGetter, Drawable.Callback {
    
        private final Context mContext;
    
        private final TextView mTextView;
    
        private final Set<ImageGetterViewTarget> mTargets;
    
        public static GlideImageGetter get(View view) {
            return (GlideImageGetter) view.getTag(R.id.drawable_callback_tag);
        }
    
        public void clear() {
            GlideImageGetter prev = get(mTextView);
            if (prev == null) return;
    
            for (ImageGetterViewTarget target : prev.mTargets) {
                Glide.clear(target);
            }
        }
    
        public GlideImageGetter(Context context, TextView textView) {
            this.mContext = context;
            this.mTextView = textView;
    
            clear();
            mTargets = new HashSet<>();
            mTextView.setTag(R.id.drawable_callback_tag, this);
        }
    
        @Override
        public Drawable getDrawable(String url) {
            final UrlDrawable urlDrawable = new UrlDrawable();
    
            Logger.i("Downloading from: " + url);
            Glide.with(mContext)
                    .load(url)
                    .diskCacheStrategy(DiskCacheStrategy.ALL)
                    .into(new ImageGetterViewTarget(mTextView, urlDrawable));
    
    
            return urlDrawable;
    
        }
    
        @Override
        public void invalidateDrawable(Drawable who) {
            mTextView.invalidate();
        }
    
        @Override
        public void scheduleDrawable(Drawable who, Runnable what, long when) {
    
        }
    
        @Override
        public void unscheduleDrawable(Drawable who, Runnable what) {
    
        }
    
        private class ImageGetterViewTarget extends ViewTarget<TextView, GlideDrawable> {
    
            private final UrlDrawable mDrawable;
    
            private ImageGetterViewTarget(TextView view, UrlDrawable drawable) {
                super(view);
                mTargets.add(this);
                this.mDrawable = drawable;
            }
    
            @Override
            public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> glideAnimation) {
                Rect rect;
                if (resource.getIntrinsicWidth() > 100) {
                    float width;
                    float height;
                    Logger.i("Image width is " + resource.getIntrinsicWidth());
                    Logger.i("View width is " + view.getWidth());
                    if (resource.getIntrinsicWidth() >= getView().getWidth()) {
                        float downScale = (float) resource.getIntrinsicWidth() / getView().getWidth();
                        width = (float) resource.getIntrinsicWidth() / (float) downScale;
                        height = (float) resource.getIntrinsicHeight() / (float) downScale;
                    } else {
                        float multiplier = (float) getView().getWidth() / resource.getIntrinsicWidth();
                        width = (float) resource.getIntrinsicWidth() * (float) multiplier;
                        height = (float) resource.getIntrinsicHeight() * (float) multiplier;
                    }
                    Logger.i("New Image width is " + width);
    
    
                    rect = new Rect(0, 0, Math.round(width), Math.round(height));
                } else {
                    rect = new Rect(0, 0, resource.getIntrinsicWidth() * 2, resource.getIntrinsicHeight() * 2);
                }
                resource.setBounds(rect);
    
                mDrawable.setBounds(rect);
                mDrawable.setDrawable(resource);
    
    
                if (resource.isAnimated()) {
                    mDrawable.setCallback(get(getView()));
                    resource.setLoopCount(GlideDrawable.LOOP_FOREVER);
                    resource.start();
                }
    
                getView().setText(getView().getText());
                getView().invalidate();
            }
    
            private Request request;
    
            @Override
            public Request getRequest() {
                return request;
            }
    
            @Override
            public void setRequest(Request request) {
                this.request = request;
            }
        }
    }
    View Code

    4.4.实现了Html.ImageGetter接口中的方法

      

      这里用到了之前定义的UrlDrawable方法了。

      将urlDrawable和textView挂钩了,利用了一个ImageGetterViewTarget类完成转换作用。

      这里同时也是实现Glide加载图片的关键,利用Glide.with().load().into()方法即可加载图片。

      

    4.5.实现了Drawable.Callback接口中的方法

      

      这里没做什么事情,就是将textView刷新一下。这样图片才能显示出来。

    4.6.然后看一下构造函数

      

      这里就是一个提供给外部调用的一个构造函数。

      将某个上下文的textView获取到。

      首先clear一下。

      然后将这个textView设置一个Tag。

      设置标签的作用==>用于区分很多相似的View。

      

      怎么clear?

      先get一下。get这个textView,获取一个GlideImageGetter,然后将其中clear。

      循环遍历GlideImageGetter中的ImageGetterViewTarget,利用Glide.clear(target)来清除。

      怎么get?

      

      返回一个GlideImageGetter,从一个资源文件:

      

      得到一个view,强制转换成GlideImageGetter。

    4.7.内部类ImageGetterViewTarget

      继承了ViewTarget<TextView,GlideDrawable>

      作用:将textView和GlideDrawable挂钩,转换的效果。

      注意:这个ViewTarget是第三方库自己提供的一个类

      

      4.7.1.构造函数

          

         存放到大佬GlideImageGetter来统一管理,所以在GlideImageGetter用到了一个集合Set。

      

      4.7.2.然后是一个定义一个成员变量Request

         

      4.7.3.最后是最难的一个复写的函数onResourceReady

         

        这个就是整个联系过程了。

        定义了边界和缩放。

         

    4.8.推荐一篇基于Glide图片加载框架==支持textView图文并茂

      文章地址:http://www.jianshu.com/p/037ae1dfb442

      实现效果:

      

    4.9.关于Android图片加载

      参考文章:Android大神之作。

       

      


    5.总计一下

    5.1.textView使用Glide加载html图片的总流程,首先由一个实现了Html.ImageGetter接口的一个ImageGetter类。

      这个Getter类要求实现getGrawable,然后这里面是一个Glide.with.load.into加载图片到一个自定义的

      ImageGetterViewTarget,这个类是ImageGetter中的内部类,主要处理将textView和GlideDrawable

      产生联系,主要联系方法是onResourceReady,主要处理了一些边界和缩放,好让图片正确显示。

    5.2.这里有一个UrlDrawable是一个辅助,辅助GlideImageGetter大佬将textView和UrlDrawable产生必要的联系。

      其实UrlDrawable里面的最关键的变量就是一个GlideDrawable,其实UrlDrawable就是起到一个过渡作用。将

      textView通过UrlDrawable得到一个GlideDrawable。这样才能处理图片的一些边界以及缩放了。

    5.3.所以这里对第三方库Glide有了更加深入的理解。如果要自定义Glide加载方式,必须要有一个自定义Module。

      注意这个Module一定要在清单中配置,否则也没有用的。然后是最重要的GlideImageGetter,这是一个自定义

      类来获取图片的,通过Html来获取其中元素。所以这里发现内部类ImageGetterViewTarget和UrlDrawable

      都是辅助,ImageGetterViewTarget重要的函数是onResourceRead来完成边界和缩放,UrlDrawable是提供

      一个将GlideDrawable封装起来的一个类,方便调用。

    5.4.Glide是一个非常强大的图片加载第三方库。很多功能都值得去探索,单纯会将图片加载到imageView并不能证明

      你就会用了。可以说现在我还是迷迷糊糊的,但是至少我比当初的我有小许了解了要怎么做,要做什么。接下来

      继续加油了,这里只是简单了解,以后碰到了再另外写一篇。

     

    既然选择了,便不顾风雨兼程。Just follow yourself.
  • 相关阅读:
    使用CuteFTP登陆FTP(servU)服务器后无法LIST目录和文件的解决方法
    delphi技巧集锦之一
    delphi技巧集锦之二
    关于varchar(max), nvarchar(max)和varbinary(max)
    别告诉我你会用WORD
    Showmodal与show的区别
    SET ANSI_NULLS ON的用法
    {右键我的电脑无法打开计算机管理}解决方法
    Word常用技巧
    Excel 使用技巧集锦——163种技巧
  • 原文地址:https://www.cnblogs.com/Jason-Jan/p/7881690.html
Copyright © 2020-2023  润新知