Android Glide学习笔记

Glide是一款针对Android的高效图片加载库,基于Picasso优化,支持RGB_565格式,磁盘缓存多规格图片,内置Gif支持。相比UniversalImageLoader和Picasso,Glide更适用于大部分项目。其工作流程包括内存和磁盘缓存、生命周期管理、RequestManager和Engine的交互。使用时,通过with、load和into方法创建请求。对于大型项目,Fresco可能是更好的选择,因为它在Native层处理图片,减少OOM风险。
摘要由CSDN通过智能技术生成

Glide是比较常用的图片加载库,因为我在项目里使用到了,所以会跟EventBus一样参考网上前辈的文章做一个学习笔记。

开源库的比较

图片加载是 Android 项目中必备的需求,而图片加载的开源库也有很多:有 UniversalImageLoader、Picasso、Fresco、Glide等。

  • UniversalImageLoader是老牌的图片加载库(我在最初的两个项目里使用的都是它)。但是作者已经不再维护项目了,所以 UniversalImageLoader不推荐在项目中使用了。
  • Picasso 是图片开源库,是Glide的基础。
  • Glide基于 Picasso 的,做了大量优化与改进。Glide 默认的 Bitmap 格式是 RGB_565 格式,而 Picasso 默认的是 ARGB_8888 格式,这个内存开销要小一半。在磁盘缓存方面,Picasso 只会缓存原始尺寸的图片,而 Glide 缓存的是多种规格。最重要的一个特性是 Glide 支持加载 Gif 动态图,而 Picasso 不支持该特性。总体来说,Glide 是在 Picasso 基础之上进行的二次开发,各个方面做了不少改进,不过这也导致他的包比 Picasso 大不少
  • Fresco 是新一代的图片加载库, Android 应用程序可用的内存有限,经常会因为图片加载导致 OOM。而 Fresco就在更底层的 Native 堆处理图片。于是 Fresco 将图片放到一个特别的内存区域叫 Ashmem 区,就是属于 Native 堆,图片将不再占用 App 的内存,Java 层对此无能为力,这里是属于 C++ 的地盘,所以能大大的减少 OOM。所以此库包也比较大,底层涉及到的 C++ 领域。
  • 大部分情况 Glide 都能满足需求,但是如果 App 中大量使用图片,那么用 Fresco是更好的选择。

设计图

引用自Glide 源码解析
Glide 源码解析

流程图

引用自Glide 源码解析
流程图

使用与简介

Glide.with(imageView.getContext())
                .load(url)
                .placeholder(defaultImage)
                .error(failImage)
                .into(imageView);

如上,Glide 库使用流接口(fluent interface)。流接口(fluent Interface)是指实现一种实现面向对象的能提高代码可读性的API的方法。Glide可以从资源,文件目录和网络上加载图片资源。当加载图片时,Glide 使用3个来源:内存,磁盘和网络(从最快到最慢排序)。Glide 建造者要求最少有三个参数:
with(Context context) ;load(String imageUrl) - 这里你可以指定哪个图片应该被加载,同上它会是一个字符串的形式表示一个网络图片的 URL;into(ImageView targetImageView) 你的图片会显示到对应的 ImageView 中。

Glide.with方法

如上一段的代码可以看出,调用了Glide类的with方法(例子里使用的是第一个)。

////获取RequestManager对象,该类实现了LifeCycleListener接口,绑定Activity/Fragment生命周期,对请求进行暂停,恢复,清除操作。
    public static RequestManager with(Context context) {
  //获取RequestManager对象
    //得到RequestManagerRetriever实例,该类将RequestManager和自定义Fragment(如RequestManagerFragment,SupportRequestManagerFragment)绑定,从而实现在生命周期管理回调。这里自定义Fragment值得注意。
        RequestManagerRetriever retriever = RequestManagerRetriever.get();//新建一个handler,handler = new Handler(Looper.getMainLooper(), this /* Callback */);RequestManagerRetriever实现了Handler.Callback。
        return retriever.get(context);
    }

    public static RequestManager with(Activity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }

    public static RequestManager with(FragmentActivity activity) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(activity);
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static RequestManager with(android.app.Fragment fragment) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(fragment);
    }

    public static RequestManager with(Fragment fragment) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        return retriever.get(fragment);
    }

可以看出,5个函数都是起先调用了RequestManagerRetriever retriever = RequestManagerRetriever.get()。他们最后都创建了RequestManager对象。

RequestManagerRetriever

    public RequestManager get(Context context) {
        if (context == null) {
            throw new IllegalArgumentException("You cannot start a load on a null Context");
        } else if (Util.isOnMainThread() && !(context instanceof Application)) {
  //判断是不是主线程,并且context不是Application的实例
            if (context instanceof FragmentActivity) {
                return get((FragmentActivity) context);
            } else if (context instanceof Activity) {
                return get((Activity) context);
            } else if (context instanceof ContextWrapper) {
                return get(((ContextWrapper) context).getBaseContext());
            }
        }

        return getApplicationManager(context);
    }

在这里,特别提到ContextWrapper,它与context的关系如下图:
这里写图片描述

如果我调用了Glide.with(imageView.getContext())的话,那么应该调用return get((FragmentActivity) context);步骤。

public RequestManager get(FragmentActivity activity) {
        if (Util.isOnBackgroundThread()) {
  //判断是否在主线程
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);//判断界面是否已经销毁了
            FragmentManager fm = activity.getSupportFragmentManager();//获取FragmentManager 对象(android.support.v4.app包带的)
            return supportFragmentGet(activity, fm);//创建Fragment,RequestManager并将其绑定
        }
    }

RequestManager/supportFragmentGet

RequestManager supportFragmentGet(Context context, FragmentManager fm) {
//获取RequestManagerFragment,主要利用Frament进行请求生命周期管理
        SupportRequestManagerFragment current = getSupportRequestManagerFragment(fm);
        RequestManager requestManager = current.getRequestManager();
        //requestManager 为空,即首次加载初始化requestManager ,并调用setRequestManager设置到RequestManagerFragment 
        if (requestManager == null) {
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);//复用
        }
        return requestManager;
    }

SupportRequestManagerFragment 是一个无界面的Fragment类,起到把请求和Activity生命周期同步的作用。上面代码主要的部分就是getSupportRequestManagerFragment函数,获取到了一个fragment。

getSupportRequestManagerFragment

RequestManagerFragment getRequestManagerFragment(FragmentManager fm) {
        RequestManagerFragment current = (RequestManagerFragment)fm.findFragmentByTag("com.bumptech.glide.manager");//强转,看看有没有以当前tag命名的fragment,不为空的话直接返回,为空的话需要创建。
        if(current == null) {
            current = (RequestManagerFragment)this.pendingRequestManagerFragments.get(fm);//pendingRequestManagerFragments是一个hashmap,创建的RequestManagerFragment 对象会存放在其中,复用。
            if(current == null) {
                current = new RequestManagerFragment();
                this.pendingRequestManagerFragments.put(fm, current);//存放在hashmap里。
                fm.beginTransaction().add(current, "com.bumptech.glide.manager").commitAllowingStateLoss();
                this.handler.obtainMessage(1, fm).sendToTarget();//发送消息,同时会把hashmap中的fragment移除(代码不贴了)
            }
        }

        return current;
    }

上面的代码中,创建RequestManagerFragment是比较关键的一步。

com.bumptech.glide.manager/RequestManagerFragment

public class RequestManagerFragment extends Fragment {
   
    private final ActivityFragmentLifecycle lifecycle;
    private final RequestManagerTreeNode requestManagerTreeNode;
    private RequestManager requestManager;
    private final HashSet<RequestManagerFragment> childRequestManagerFragments;
    private RequestManagerFragment rootRequestManagerFragment;

    public RequestManag
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值