Glide请求的管理

我们在使用Glide的时候,展示一张图片,只需这样一行代

Glide.with(Activity/Fragment/Context).load(url).into(imageView);

这行代码的字面意思挺好理解,传入当前的上下文,下载给定url的图片,然后将图片展示到传入的ImageView上。

既然是下载图片,就肯定是网络或者IO操作,那么肯定是开了一个线程去操作的。由此就有可能会出现一个问题,假如我们进入一个Activity,然后加载一个图片,在加载完成之前,我们退出当前的Activity,按理来说在退出前应该停止加载图片吧,不然可能会浪费多余的资源或者出现内存泄漏,但是我们并没有在生命周期中调用任何Glide的相关的其他方法,那么Glide肯定做了什么我们不知道东西。

看看它的具体是如何实现的。

从with方法开始看,发现它有几个重载的方法

public static RequestManager with(Context context) {
        RequestManagerRetriever retriever = RequestManagerRetriever.get();
        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);
    }

RequestManagerRetriever

可以看出RequestManagerRetriever是一个单例,然后调用他的get方法,获得一个RequestManger,感觉从字面意思好像能大概理解它们有什么作用。RequestManagerRetriever的get方法也有几个重载方法,看其中的几个,作用都差不多,但是如果传入的Application,会有些不同,简单点说就是请求的生命周期跟你传入的参数对应的组件的生命周期对应

 public RequestManager get(Fragment fragment) {
        if (fragment.getActivity() == null) {
            throw new IllegalArgumentException("You cannot start a load on a fragment before it is attached");
        }
        //如果当前不是在主线程上,就使用applicationContext作为参数
        if (Util.isOnBackgroundThread()) {
            return get(fragment.getActivity().getApplicationContext());
        } else {
            //当前的参数是Fragment,说明是在Fragment中加载图片,
            //获取到当前Fragment内部管理Fragment的FragmentManager
            FragmentManager fm = fragment.getChildFragmentManager();
            return supportFragmentGet(fragment.getActivity(), fm);
        }
    }

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public RequestManager get(Activity activity) {
        if (Util.isOnBackgroundThread() || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
            return get(activity.getApplicationContext());
        } else {
            assertNotDestroyed(activity);
            android.app.FragmentManager fm = activity.getFragmentManager();
            return fragmentGet(activity, fm);
        }
    }

    private RequestManager getApplicationManager(Context context) {
        // Either an application context or we're on a background thread.
        if (applicationManager == null) {
            synchronized (this) {
                if (applicationManager == null) {
                    // Normally pause/resume is taken care of by the fragment we add to the fragment or activity.
                    // However, in this case since the manager attached to the application will not receive lifecycle
                    // events, we must force the manager to start resumed using ApplicationLifecycle.
                    applicationManager = new RequestManager(context.getApplicationContext(),
                            new ApplicationLifecycle(), new EmptyRequestManagerTreeNode());
                }
            }
        }

        return applicationManager;
    }

除了传入的是ApplicationContext参数的,其余的都会调用到fragmentGet方法

RequestManager fragmentGet(Context context, android.app.FragmentManager fm) {
        //获取或者创建管理请求的Fragment
        RequestManagerFragment current = getRequestManagerFragment(fm);
        //获取当前的请求管理者,如果为空就创建一个
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
            //关注一下current.getLifecycle()这个参数,用于监听Fragment的生命周期
            requestManager = new RequestManager(context, current.getLifecycle(), current.getRequestManagerTreeNode());
            current.setRequestManager(requestManager);
        }
        return requestManager;
    }

RequestManager

1、它实现了LifecycleListener,LifecycleListener中有onStart、onStop、onDestroy方法;
2、RequestManager中有一个Lifecycle属性,它来自它其实是ActivityFragmentLifecycle,来源于RequestManagerFragment,用于监听RequestManagerFragment的生命周期;
3、ActivityFragmentLifecycle会将当期的LifecycleListener(RequestManager)保存起来,等RequestManagerFragment生命周期变化的时候回调RequestManager的onStart、onStop、onDestroy方法

public class RequestManager implements LifecycleListener {
    private final Context context;
    //用于监听Activity/Fragment的生命周期
    private final Lifecycle lifecycle;
    //Activity、Fragment里面会嵌套多层Fragment,所以会有多个RequestManager,通过它可以获取所以的requestManager
    private final RequestManagerTreeNode treeNode;
    //用于跟踪,取消和重新启动正在进行,已完成和失败的请求
    private final RequestTracker requestTracker;
    private final Glide glide;
    //请求设置相关
    private final OptionsApplier optionsApplier;
    private DefaultOptions options;

    RequestManager(Context context, final Lifecycle lifecycle, RequestManagerTreeNode treeNode,
            RequestTracker requestTracker, ConnectivityMonitorFactory factory) {
        this.context = context.getApplicationContext();
        this.lifecycle = lifecycle;
        this.treeNode = treeNode;
        this.requestTracker = requestTracker;
        this.glide = Glide.get(context);
        this.optionsApplier = new OptionsApplier();
        //网络连接变化监听
        ConnectivityMonitor connectivityMonitor = factory.build(context,
                new RequestManagerConnectivityListener(requestTracker));

        // If we're the application level request manager, we may be created on a background thread. In that case we
        // cannot risk synchronously pausing or resuming requests, so we hack around the issue by delaying adding
        // ourselves as a lifecycle listener by posting to the main thread. This should be entirely safe.
        if (Util.isOnBackgroundThread()) {
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    lifecycle.addListener(RequestManager.this);
                }
            });
        } else {
            //将当期的requestManager加入到生命周期管理ActivityFragmentLifecycle中,
            //当Fragment的生命周期变化是会执行ActivityFragmentLifecycle对应的方法,然后就会回调requestManager当前的onStart、onStop、onDestroy
            lifecycle.addListener(this);
        }
        lifecycle.addListener(connectivityMonitor);
    }
  @Override
    public void onStart() {
        // onStart might not be called because this object may be created after the fragment/activity's onStart method.
        resumeRequests();
    }

    /**
     * Lifecycle callback that unregisters for connectivity events (if the android.permission.ACCESS_NETWORK_STATE
     * permission is present) and pauses in progress loads.
     */
    @Override
    public void onStop() {
        pauseRequests();
    }

    /**
     * Lifecycle callback that cancels all in progress requests and clears and recycles resources for all completed
     * requests.
     */
    @Override
    public void onDestroy() {
        requestTracker.clearRequests();
    }

    public void resumeRequests() {
        Util.assertMainThread();
        requestTracker.resumeRequests();
    }
    public void pauseRequests() {
        Util.assertMainThread();
        requestTracker.pauseRequests();
    }

RequestTracker

用于跟踪,取消和重新启动正在进行,已完成和失败的请求
它保存了当前RequestManagerFragment中的所有具体请求对象Request,它有如下方法,从方法名就可以看出意思

addRequest
clearRequests
pauseRequests
removeRequest
restartRequests
resumeRequests
runRequest

总结

简单点说,Glide请求的管理其实就是
1、通过RequestManagerRetriever创建一个不可见的RequestManagerFragment与对应的一个RequestManager
2、RequestManagerFragment的生命周期通过ActivityFragmentLifecycle传递到RequestManager
3、RequestManager中的生命周期回调,RequestTracker执行具体的请求的开始、停止
源码阅读没必要一股脑的看这个流程,那样不太容易理解,我们可以从某一小块入手,我们可以从包名大概看出一些门道,大概理解其中代表什么功能,然后各个去看


image.png
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容